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:
- read
GET /v1/payments/{payment_id} - if the payment is
CONFIRMED, read memberships and receipts - 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:
- confirm the payment and membership state in Hilt
- issue the refund on-chain from the merchant side
- record the support trail in Hilt
- 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:
BILLINGAPI_ERRORFEATURE_REQUESTCOMPLIANCEOTHER
Common failures:
422category invalid422message 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:
- let the buyer complete hosted checkout
- keep the
payment_id - read payment status until terminal
- inspect or search memberships for access state
- inspect receipts when you need public proof or support evidence
- 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.