Skip to main content

Members, Receipts, Support, and Billing

Once a payment settles, Hilt becomes an operating surface: member lookup, receipt verification, support context, and merchant billing.

If you are thinking about this from a payment-systems point of view, keep one thing in mind:

  • payment success is asynchronous
  • Hilt may reach the final state through hosted confirmation, Helius settlement, or both
  • your operating source of truth is the Hilt payment, membership, and receipt surface, not a wallet screenshot

For the provider side of that model, see Webhooks.

Membership routes

List memberships

GET /v1/memberships?product_id=uuid&status=ACTIVE&platform=TELEGRAM&q=crzy&limit=20&offset=0
X-Hilt-Key: hk_live_...

Response:

{
"items": [],
"count": 0
}

The membership list is designed for merchant operations, not just raw payment inspection. It is the main route for showing:

  • current access state
  • platform identity
  • latest transaction
  • renewal date
  • delivery state

Lookup memberships

GET /v1/memberships/lookup?wallet=BuyerWallet...
GET /v1/memberships/lookup?identity=@crzypeas
GET /v1/memberships/lookup?tx_signature=5zLCm5...

This is the fastest path for support tooling and automation.

Get one membership

GET /v1/memberships/{membership_id}

Save merchant notes

PATCH /v1/memberships/{membership_id}/notes
Content-Type: application/json
{
"notes": "Buyer is part of a managed migration cohort."
}

Update member display details

PATCH /v1/memberships/{membership_id}/profile
Content-Type: application/json
{
"platform_display": "@crzypeas"
}

Gift extra access

POST /v1/memberships/{membership_id}/gift
Content-Type: application/json
{
"days": 30,
"note": "Courtesy extension while we fix delivery automation."
}

Retry delivery

POST /v1/memberships/{membership_id}/retry-delivery

Use this when a membership is valid but the access handoff failed or needs re-running.

Payment status after checkout

The buyer-facing flow usually reaches you through a payment_id.

The safest follow-up sequence is:

  1. read GET /v1/payments/{payment_id}
  2. if the payment is CONFIRMED, read memberships and receipts
  3. if delivery is the only thing that failed, retry delivery instead of replaying the payment

This is especially important for mobile wallet flows where the chain transaction may be real before the UI has fully caught up.

Receipt routes

There are two receipt surfaces:

  • merchant-authenticated receipt retrieval
  • public verification for audit and sharing

Generate a receipt manually

POST /v1/receipt
Authorization: Bearer <jwt>
Content-Type: application/json
{
"tx_sig": "5zLCm5...",
"wallet": "BuyerWallet1111111111111111111111111111111111",
"counterparty_wallet": "So1anaMerchantWallet1111111111111111111111111",
"token_mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"amount_raw": 200000,
"memo": "HILT:nonce"
}

This route is credit-metered and idempotent on tx_sig.

Get a receipt

GET /v1/receipt/{receipt_id}
Authorization: Bearer <jwt>

Representative response:

{
"receipt_id": "uuid",
"receipt_json": {
"transaction": {
"tx_sig": "5zLCm5...",
"amount_raw": 200000,
"token_mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"memo": "HILT:nonce"
}
},
"receipt_hash": "sha256_hash",
"ed25519_sig": "signature",
"schema_version": "1.0",
"created_at": "2026-04-14T12:00:00+00:00Z",
"verify_url": "https://api.hilt.so/v1/receipt/uuid/verify",
"credits_burned": 0
}

Verify a receipt publicly

GET /v1/receipt/{receipt_id}/verify

This does not require auth. It re-checks the receipt hash and Ed25519 signature.

List receipts

GET /v1/receipts?page=1&per_page=20&wallet=BuyerWallet...
Authorization: Bearer <jwt>

Representative response:

{
"total": 3,
"page": 1,
"per_page": 20,
"receipts": [
{
"receipt_id": "uuid",
"tx_sig": "5zLCm5...",
"receipt_hash": "hash",
"schema_version": "1.0",
"created_at": "2026-04-14T12:00:00+00:00Z",
"verify_url": "https://api.hilt.so/v1/receipt/uuid/verify"
}
]
}

Refunds and reversals

Hilt’s buyer checkout is non-custodial.

So the refund story is different from a card processor:

  • the buyer’s original payment is still a real on-chain payment
  • a refund is a separate merchant-initiated payout or settlement decision
  • the original receipt remains a proof of the original payment event

Recommended merchant flow:

  1. confirm the payment and membership state in Hilt
  2. issue the refund on-chain from the merchant side
  3. record the support trail in Hilt
  4. if access should no longer remain active, update the member operationally after the refund decision

For Hilt’s own SaaS billing, disputes and refunds are part of Stripe billing, not the on-chain buyer payment trail.

Support routes

Create a support ticket

POST /v1/support/tickets
Authorization: Bearer <jwt>
Content-Type: application/json
{
"subject": "Buyer says access did not arrive",
"category": "OTHER",
"body": "Transaction confirmed, but the buyer did not get the Telegram invite."
}

Successful response:

{
"ticket_id": "hilt_ticket_...",
"status": "OPEN",
"subject": "Buyer says access did not arrive",
"category": "OTHER"
}

Valid categories:

  • BILLING
  • API_ERROR
  • FEATURE_REQUEST
  • COMPLIANCE
  • OTHER

Common failures:

  • 422 category invalid
  • 422 message too short

List tickets

GET /v1/support/tickets?status=OPEN&page=1&per_page=20

Get one ticket thread

GET /v1/support/tickets/{ticket_id}

Add a ticket message

POST /v1/support/tickets/{ticket_id}/message
Content-Type: application/json
{
"body": "We have retried delivery and confirmed the member record is active."
}

If a ticket was waiting on the merchant and you post again, Hilt reopens it.

Merchant billing routes

Stripe is used for Hilt’s own merchant subscription billing, not the on-chain buyer checkout flow.

Billing summary

GET /v1/billing/summary
Authorization: Bearer <jwt>

This returns:

  • current Hilt tier
  • billing status and interval
  • Stripe customer and subscription ids
  • live template counts and plan limits
  • Hilt fee rates
  • merchant payment totals by asset
  • USDC equivalent totals
  • live SOL price used for the conversion
  • recent Stripe invoice history

Start Stripe checkout for a Hilt plan

POST /v1/billing/checkout/stripe
Content-Type: application/json
{
"plan": "growth",
"interval": "monthly",
"success_url": "https://app.hilt.so/dashboard/billing?stripe=success",
"cancel_url": "https://app.hilt.so/dashboard/billing?stripe=cancel"
}

Open Stripe billing portal

POST /v1/billing/portal/stripe
Content-Type: application/json
{
"return_url": "https://app.hilt.so/dashboard/billing"
}

Refresh Stripe billing state

POST /v1/billing/refresh/stripe

Use this after a completed Stripe checkout if you want to force a subscription-state sync.

Recommended post-payment operating loop

For most teams, the clean operating loop is:

  1. let the buyer complete hosted checkout
  2. keep the payment_id
  3. read payment status until terminal
  4. inspect or search memberships for access state
  5. inspect receipts when you need public proof or support evidence
  6. create or reply to support tickets when a human follow-up is needed

That keeps your backend, dashboard, and support tooling aligned around the same Hilt objects.