Skip to content

Configuration

Before creating invoices, you need a checkout configuration. Each user has one config that stores shared checkout settings, while payment rails are managed separately as payment methods.

Get configuration

GET /api/checkout/config

Returns your current checkout config, or 404 if not configured yet.

Response:

json
{
  "config": {
    "id": "uuid",
    "defaultPaymentTiming": {
      "mode": "immediate",
      "expiresAfterMinutes": 20
    },
    "bitcoinPostExpiryGraceMinutes": 480,
    "invoiceIssuerName": "Acme, Inc.",
    "sendInvoiceCreatedEmail": true,
    "sendInvoicePaidEmail": true,
    "invoiceCreateFields": {
      "productName": true,
      "issuedBy": true,
      "billTo": true,
      "redirectUrl": true,
      "paymentTiming": false,
      "merchantReference": false,
      "customerId": false,
      "customerEmail": false,
      "merchantNote": false
    },
    "webhookUrl": "https://yoursite.com/webhook",
    "redirectUrl": "https://yoursite.com/thank-you",
    "webhookSecretConfigured": true,
    "paymentMethods": [
      {
        "id": "uuid",
        "methodType": "bitcoin",
        "label": "Bitcoin",
        "assetCode": "BTC",
        "network": "bitcoin",
        "enabled": true,
        "railTypes": ["address_transfer"],
        "hasSecret": true,
        "config": {
          "requiredConfirmations": 1
        }
      }
    ],
    "supportedEthereumTokens": [
      {
        "assetCode": "USDT",
        "network": "ethereum",
        "chainId": 1,
        "displayName": "Tether USD",
        "contractAddress": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
        "decimals": 6,
        "defaultConfirmations": 14
      },
      {
        "assetCode": "USDC",
        "network": "ethereum",
        "chainId": 1,
        "displayName": "USD Coin",
        "contractAddress": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
        "decimals": 6,
        "defaultConfirmations": 14
      }
    ],
    "createdAt": "2025-01-10T08:00:00.000Z",
    "updatedAt": "2025-01-15T12:00:00.000Z"
  }
}

Create or update configuration

PUT /api/checkout/config

Creates a new config or updates the existing one. Shared settings live on the config, while wallet rails are supplied through paymentMethods[].

Request body:

FieldTypeRequiredDescription
defaultPaymentTimingobjectNoDefault payment timing for new invoices. See the shapes below.
bitcoinPostExpiryGraceMinutesintegerNoAfter a Bitcoin invoice becomes no longer payable, how long to keep watching detected BTC payments before marking it expired or underpaid. 1–720 (12h). Default: 120 (2h).
invoiceIssuerNamestringNoDefault issuedBy value for new invoices and the organization name shown on hosted invoices. Max 120 chars.
sendInvoiceCreatedEmailbooleanNoSend checkout customer email when a due-date invoice is created. Ignored for immediate invoices. Default: false.
sendInvoicePaidEmailbooleanNoSend checkout customer email on the first transition into paid. Default: false.
invoiceCreateFieldsobjectNoDashboard setting that controls which optional fields appear in the internal create-invoice form.
webhookUrlstringNoWebhook URL for payment notifications. Must be a valid URL.
redirectUrlstringNoDefault redirect URL after payment confirms. Can be overridden per invoice.
paymentMethodsarrayNoFull desired payment-method set. Omitting a method disables it.

Example:

bash
curl -X PUT \
  -H "Authorization: Bearer <jwt>" \
  -H "Content-Type: application/json" \
  -d '{
    "defaultPaymentTiming": {
      "mode": "immediate",
      "expiresAfterMinutes": 30
    },
    "invoiceIssuerName": "Acme, Inc.",
    "sendInvoiceCreatedEmail": true,
    "sendInvoicePaidEmail": true,
    "invoiceCreateFields": {
      "productName": true,
      "issuedBy": true,
      "billTo": true,
      "redirectUrl": true,
      "paymentTiming": false,
      "merchantReference": false,
      "customerId": false,
      "customerEmail": false,
      "merchantNote": false
    },
    "webhookUrl": "https://yoursite.com/webhook",
    "paymentMethods": [
      {
        "methodType": "bitcoin",
        "label": "Bitcoin",
        "assetCode": "BTC",
        "network": "bitcoin",
        "enabled": true,
        "railTypes": ["address_transfer"],
        "secret": "xpub6CUGRU...",
        "config": {
          "requiredConfirmations": 1
        }
      },
      {
        "methodType": "ethereum",
        "label": "USDT on Ethereum",
        "assetCode": "USDT",
        "network": "ethereum",
        "enabled": true,
        "railTypes": ["wallet_contract", "address_transfer"],
        "config": {
          "recipient": "0x1111111111111111111111111111111111111111",
          "requiredConfirmations": 14
        }
      }
    ]
  }' \
  https://fincobra.com/api/checkout/config

Error responses:

StatusError
400Validation failed (invalid URL, invalid payment timing, unsupported config, etc.)
409Payment method or API key conflict

Payment timing shapes

Immediate

Use this for standard checkout flows with a countdown timer:

json
{
  "defaultPaymentTiming": {
    "mode": "immediate",
    "expiresAfterMinutes": 20
  }
}
  • expiresAfterMinutes: 1 to 1440

With due date

Use this when an invoice should remain payable through a due date and an optional grace period:

json
{
  "defaultPaymentTiming": {
    "mode": "due_date",
    "dueAfterDays": 7,
    "gracePeriodDays": 14
  }
}
  • dueAfterDays: 1 to 60
  • gracePeriodDays: 0 to 90

Due-date invoices do not show a live expiration countdown. They remain payable until the final payable deadline (dueAt + gracePeriodDays) and then expire.

Get wallet balance

GET /api/checkout/config/balance

Returns the current Bitcoin-method balance derived from the configured Bitcoin payment method via Electrum.

Response:

json
{
  "assetCode": "BTC",
  "network": "bitcoin",
  "confirmedAmount": 0.0042,
  "unconfirmedAmount": 0.001,
  "totalAmount": 0.0052,
  "totalUsd": 520.0,
  "quoteRate": 100000
}
FieldTypeDescription
assetCodestringCurrent checkout asset code
networkstringCurrent checkout payment network
confirmedAmountnumberConfirmed balance in the quoted checkout asset
unconfirmedAmountnumberUnconfirmed (mempool) balance in the same asset
totalAmountnumberTotal balance (confirmed + unconfirmed)
totalUsdnumberTotal balance converted to USD
quoteRatenumberCurrent asset/USD exchange rate used

Configuration fields reference

FieldDescription
idUnique config ID (UUID)
webhookSecretConfiguredtrue when a webhook signing secret exists
paymentMethodsConfigured payment rails and their sanitized method config
supportedEthereumTokensCanonical Ethereum stablecoins supported by checkout
defaultPaymentTimingDefault payment timing for new invoices
bitcoinPostExpiryGraceMinutesHow long to keep watching detected BTC payments after the final payable deadline
invoiceIssuerNameDefault issuedBy value for new invoices and the organization shown on hosted invoices
sendInvoiceCreatedEmailSends a checkout email when a due-date invoice is created for a customer
sendInvoicePaidEmailSends a checkout email the first time an invoice becomes paid
invoiceCreateFieldsWhich optional fields appear in the dashboard create-invoice form
webhookUrlWebhook endpoint for payment events
redirectUrlDefault post-payment redirect URL

Rotate webhook secret

POST /api/checkout/config/webhook-secret/rotate

Rotates the HMAC signing secret used for webhook delivery and returns the new value immediately:

json
{
  "webhookSecret": "new-secret-value"
}

WARNING

After rotating the secret, update your webhook consumer before accepting more events. Requests signed with the old secret will stop validating immediately.

The GET /api/checkout/config response does not return the current secret again. The new value is only shown by the rotate response.