Products and checkout

If you are integrating Hilt into your own product, this is the core public runtime surface:
  • products
  • hosted checkout
  • identity handoff
  • payment broadcast
  • payment confirmation
  • payment status

The basic model

  1. a merchant publishes a template in the dashboard
  2. your backend reads or manages that same object as a product
  3. the buyer opens the hosted checkout
  4. the buyer pays
  5. Hilt confirms the payment and updates the merchant trail

Auth model

Use:
  • X-Hilt-Key for server-side backend or bot integrations
  • Authorization: Bearer JWT_TOKEN for session-assisted merchant tools
  • no auth for the public buyer payload and buyer session start

Supported product routes

These are the main merchant-managed routes:
POST   /v1/products
GET    /v1/products
GET    /v1/products/{product_id}
PATCH  /v1/products/{product_id}
DELETE /v1/products/{product_id}
GET    /v1/products/{product_id}/payments
GET    /v1/products/{product_id}/analytics
POST   /v1/products/{product_id}/handoff-link

Product route guidance

RouteUse it when
POST /v1/productsYou want to create a new offer from your own backend
GET /v1/productsYou need the merchant’s launched product list
GET /v1/products/{product_id}You need the full stored definition for one product
PATCH /v1/products/{product_id}You want to update pricing, destination, or metadata
DELETE /v1/products/{product_id}You want to archive a product from sale
GET /v1/products/{product_id}/paymentsYou want the payment trail for one product
GET /v1/products/{product_id}/analyticsYou want product-level performance data
POST /v1/products/{product_id}/handoff-linkYour backend already knows the buyer identity before checkout

Create a product

Use POST /v1/products when your backend needs to create the same kind of offer a merchant could otherwise launch from the dashboard.
curl -X POST https://api.hilt.so/v1/products \
  -H "X-Hilt-Key: hk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "product_type": "PAYMENT_LINK",
    "title": "Telegram Inner Circle",
    "description": "Monthly paid access",
    "amount_minor_units": 29000000,
    "token_mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
    "merchant_wallet": "So1anaMerchantWallet1111111111111111111111111",
    "delivery_type": "TELEGRAM_INVITE",
    "delivery_value": "https://t.me/+privateinvite",
    "membership_config": {
      "enabled": true,
      "platform": "TELEGRAM",
      "identity_type": "TELEGRAM_USER_ID",
      "billing_interval_days": 30,
      "grace_period_days": 3
    }
  }'
Representative response:
{
  "id": "ae9673c8-95db-4b39-bc2c-b5e6d5dfd9d3",
  "slug": "fmilodej",
  "status": "ACTIVE",
  "product_type": "PAYMENT_LINK",
  "title": "Telegram Inner Circle",
  "amount_minor_units": 29000000,
  "token_mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
  "merchant_wallet": "So1anaMerchantWallet1111111111111111111111111",
  "delivery_type": "TELEGRAM_INVITE",
  "delivery_value": "https://t.me/+privateinvite"
}

Product request fields

FieldRequiredMeaning
product_typeyesUse PAYMENT_LINK for a fixed-price hosted checkout
titleyesBuyer-facing offer name
descriptionnoBuyer-facing offer description
amount_minor_unitsyes for payment linksPrice in minor units of the selected asset
token_mintnoAsset mint; for launch, this is usually USDC on Solana
merchant_walletyesMerchant payout wallet
delivery_typeyesWhat the buyer receives after payment
delivery_valuenoThe invite, redirect, or delivery target
membership_confignoRenewal and identity settings for access flows

Membership fields worth setting deliberately

For recurring or gated access products, these are the fields that most affect the buyer flow:
FieldWhy it matters
membership_config.enabledTurns the product into an access-bearing flow
membership_config.platformTells Hilt which access surface the merchant is using
membership_config.identity_typeDefines what buyer identity must be tied to the payment
membership_config.billing_interval_daysDefines renewal length
membership_config.grace_period_daysGives the merchant a post-expiry cushion before access fully lapses

Read products for a workspace

curl "https://api.hilt.so/v1/products?limit=20&offset=0" \
  -H "X-Hilt-Key: hk_live_..."
Representative response:
{
  "items": [
    {
      "id": "ae9673c8-95db-4b39-bc2c-b5e6d5dfd9d3",
      "slug": "fmilodej",
      "title": "Telegram Inner Circle",
      "status": "ACTIVE",
      "product_type": "PAYMENT_LINK",
      "amount_minor_units": 29000000,
      "payment_count": 12
    }
  ],
  "count": 1
}

Update a product

Use PATCH /v1/products/{product_id} when the merchant changes the offer rather than creating a second one.
curl -X PATCH https://api.hilt.so/v1/products/ae9673c8-95db-4b39-bc2c-b5e6d5dfd9d3 \
  -H "X-Hilt-Key: hk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Telegram Inner Circle Pro",
    "description": "Monthly paid access with live calls",
    "delivery_value": "https://t.me/+updatedinvite"
  }'

Archive a product

curl -X DELETE https://api.hilt.so/v1/products/ae9673c8-95db-4b39-bc2c-b5e6d5dfd9d3 \
  -H "X-Hilt-Key: hk_live_..."

Supported public checkout routes

These are the main public buyer-flow routes:
GET   /v1/products/p/{slug}
POST  /v1/products/p/{slug}/connect
POST  /v1/products/p/{slug}/resolve-handoff
POST  /v1/pay/broadcast
POST  /v1/pay/confirm
GET   /v1/payments/{payment_id}

Read the public checkout payload

curl https://api.hilt.so/v1/products/p/example-slug
Representative response:
{
  "id": "ae9673c8-95db-4b39-bc2c-b5e6d5dfd9d3",
  "slug": "example-slug",
  "title": "Telegram Inner Circle",
  "amount_minor_units": 29000000,
  "token_mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
  "merchant_wallet": "So1anaMerchantWallet1111111111111111111111111",
  "membership_enabled": true,
  "membership_platform": "TELEGRAM",
  "membership_identity_type": "TELEGRAM_USER_ID",
  "membership_billing_interval_days": 30,
  "checkout_config": {
    "default_route": "phantom",
    "payment_asset": "USDC",
    "payment_chain": "SOLANA"
  }
}
Use this when you want to inspect the buyer-facing product data Hilt will render in hosted checkout.

Checkout payload fields that matter most

FieldMeaning
title / descriptionBuyer-facing offer copy
amount_minor_unitsPublished buyer price in minor units
merchant_walletWallet that receives the merchant payout
membership_*Membership and identity requirements
checkout_config.default_routeWhich payment lane the hosted checkout prefers first
checkout_config.payment_assetAsset label shown in checkout
checkout_config.identity_connectPlatform-native buyer connect actions when available

Start a buyer checkout session

curl -X POST https://api.hilt.so/v1/products/p/example-slug/connect \
  -H "Content-Type: application/json" \
  -d '{
    "payer_wallet": "BuyerWallet1111111111111111111111111111111111"
  }'
Representative response:
{
  "payment_id": "f0f4e620-1ca3-4fc8-b0ba-2d04342fe467",
  "nonce": "9b6f0f7e0d1c...",
  "amount_minor_units": 29000000,
  "merchant_amount_minor_units": 28971000,
  "fee_minor_units": 29000,
  "fee_wallet": "FeeWallet11111111111111111111111111111111111",
  "token_mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
  "asset_symbol": "USDC",
  "asset_decimals": 6,
  "merchant_wallet": "So1anaMerchantWallet1111111111111111111111111",
  "status": "PENDING_SIGNATURE",
  "expires_at": "2026-04-16T14:37:45.102398+00:00"
}
This returns the canonical payment_id your integration should keep all the way through confirmation and post-payment lookups.

Connect response fields

FieldMeaning
payment_idCanonical Hilt payment identifier
amount_minor_unitsBuyer total in minor units
merchant_amount_minor_unitsEstimated merchant net after Hilt fees
fee_minor_unitsHilt fee amount for this payment
asset_symbolDisplay asset such as USDC or SOL
expires_atSession expiry timestamp
phantom_mobilePresent when mobile Phantom app-switch is available

Resolve a handoff token in checkout

If the buyer arrives with a signed handoff token, the checkout can resolve it before payment:
curl -X POST https://api.hilt.so/v1/products/p/example-slug/resolve-handoff \
  -H "Content-Type: application/json" \
  -d '{
    "handoff_token": "hilt_handoff_..."
  }'
This is the route that turns a buyer-specific link into a locked identity at checkout. Use a handoff link when your bot or backend already knows who the buyer is before checkout starts.
curl -X POST https://api.hilt.so/v1/products/PRODUCT_ID/handoff-link \
  -H "X-Hilt-Key: hk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "identity_value": "728255790",
    "identity_display": "@crzypeas",
    "identity_type": "TELEGRAM_USER_ID",
    "expires_in_minutes": 30
  }'
Representative response:
{
  "handoff_token": "hilt_handoff_...",
  "expires_at": "2026-04-16T18:30:00Z",
  "checkout_url": "https://www.hilt.so/p/example-slug?handoff=hilt_handoff_..."
}
The handoff token is the cleanest way to avoid asking buyers to type a Telegram or Discord identity manually.

Hosted checkout versus custom wallet orchestration

If you use the standard hosted checkout, the typical public flow is:
  1. GET /v1/products/p/{slug}
  2. POST /v1/products/p/{slug}/connect
  3. Hilt-hosted buyer wallet flow
  4. GET /v1/payments/{payment_id}
If you are running a more custom wallet surface, you may also call:
POST /v1/pay/broadcast
POST /v1/pay/confirm
Those routes are for integrations that need to carry a signed transaction or explicit confirmation step through their own app flow. Most teams do not need them on day one.

Confirm a payment

curl -X POST https://api.hilt.so/v1/pay/confirm \
  -H "Content-Type: application/json" \
  -d '{
    "payment_id": "f0f4e620-1ca3-4fc8-b0ba-2d04342fe467",
    "slug": "example-slug",
    "tx_signature": "5zLCm5rz1gJaGgEU97UtWDxPmk4uuhoVQETQ4ukdzEqxYuM2igczQ6JbdZeZSeT9opxjqDWnni47KTPrttQ2epkz",
    "payer_wallet": "BuyerWallet1111111111111111111111111111111111"
  }'
Representative response:
{
  "status": "CONFIRMED",
  "payment_id": "f0f4e620-1ca3-4fc8-b0ba-2d04342fe467",
  "delivery_type": "TELEGRAM_INVITE",
  "delivery_value": "https://t.me/+privateinvite",
  "amount_minor_units": 29000000,
  "delivery_status": "SENT",
  "membership_id": "0ce94832-4da4-4f47-a7df-9505817d7022",
  "membership_status": "ACTIVE",
  "membership_period_end_at": "2026-05-16T14:38:08.505064+00:00"
}

Confirm response fields

FieldMeaning
statusFinal payment state returned by the confirmation path
payment_idCanonical Hilt payment identifier
delivery_type / delivery_valueWhat the buyer receives after payment
delivery_statusAccess handoff state
membership_idMembership record created or extended by the payment
membership_statusCurrent membership status
membership_period_end_atRenewal or access end timestamp when relevant

Poll payment status

curl https://api.hilt.so/v1/payments/PAYMENT_ID
Treat these states as the important ones:
  • PENDING_SIGNATURE
  • PENDING_CONFIRMATION
  • CONFIRMED
  • FAILED
In practice, most integrations should treat CONFIRMED and FAILED as terminal and everything else as transitional. Expired sessions typically surface as 410 during the session flow or as FAILED with an expiry-style failure reason.

What to persist from checkout

Persist at least:
  • product_id
  • slug
  • payment_id
  • tx_signature once it exists
  • your own buyer reference if you already know it
That gives you a clean way to reconcile what your app knows with what Hilt later confirms.

Good integration patterns

Use this pattern when you want the cleanest production integration:
  1. create or update the product from your backend when needed
  2. use the hosted checkout slug as the buyer entry point
  3. generate a handoff link if the buyer identity is already known
  4. keep the payment_id
  5. poll GET /v1/payments/{payment_id} until terminal
  6. read memberships and receipts after confirmation
That keeps your backend logic small and lets Hilt stay the source of truth for the payment trail.

What not to build

Do not build your own parallel truth from:
  • wallet screenshots
  • uncorrelated transaction lookups
  • assumptions about behavior outside the supported Hilt contract
The supported contract is:
  • hosted checkout
  • Hilt payment status
  • Hilt memberships
  • Hilt receipts