Join our community of builders on Discord!

Payment

Every completion is one job on chain, and the job's fee is paid in LCAI from a prepaid balance in the JobRegistry contract. The API never holds your funds. There are two ways to pay, and a 402 to a call with an API key lists both in accepts:
  • The delegate path: the wallet behind the API key authorizes the API once, and every call is debited from that wallet's balance with no signature per call.
  • Pay per call (experimental): each call carries a signed debit authorization against a payer's balance. No delegate is set up beforehand, and no API key is needed, so an agent that only holds a funded wallet key can pay as it goes.

The delegate path

One transaction from your wallet sets everything up:
CodeSOLIDITY
It adds the value you send to your prepaid balance, authorizes the API's signer (delegate) to submit jobs for you, and raises that delegate's allowance by the same value. From then on each completion is debited from the balance without any signature from you. The allowance caps what the API can spend for your wallet, across all its keys. You do not need to look up the contract or the delegate. Make a completion call; while the wallet is not set up, it answers 402 with the transaction to send:
CodeJSON
minimum_value_wei is one job's fee. Send more to cover more calls.
CodeTYPESCRIPT
CodeBASH
The OpenAI SDKs have no 402 class: a 402 arrives as a plain API error with status 402, and the extra fields sit inside its error object.

402 codes

codeMeansWhat to do
delegate_not_authorizedThe wallet has not authorized the API's signer.Send the accepts instruction.
insufficient_balanceThe prepaid balance cannot cover the job.Send it again to top up.
allowance_exhaustedThe API has spent everything you allowed it.Send it again: it adds balance and allowance.
spend_cap_exceededThe key reached its own lifetime cap (spend_cap_wei).Raise or remove the key's cap (PATCH /api/api-keys/{id}, or the chat's API keys page).
Only the first three carry accepts: the last is a limit you set, not a missing payment. Per-call payments sent with the key count against its cap too, and do not lift it. A call with no API key gets the pay-per-call codes below instead.

Check, withdraw, revoke

CodeBASH
Revoking the delegate also zeroes its allowance: every key of the wallet stops being able to spend until you authorize it again.

Pay per call (experimental)

Experimental: this payment method and its prepaid-debit scheme may change. It uses the x402 v2 headers (PAYMENT-REQUIRED, PAYMENT-SIGNATURE, PAYMENT-RESPONSE) with LightChain's own scheme, so standard x402 clients can't pay it: use @lightchainai/sdk, or sign as shown below.
A call can carry its own payment: an x402 PAYMENT-SIGNATURE header holding an EIP-712 debit authorization (payer, cap, single-use nonce, deadline). The API checks it, then settles it: one JobRegistry call verifies the signature, submits the job, and debits the job's fee (at most the cap) from the payer's prepaid balance. The payer needs no delegate, only a balance: a signature cannot move LCAI, so deposit once from the payer's wallet.
CodeBASH
The API key is optional. A request with no Authorization header is paid and authenticated by its payment alone, and its payer is held to per-payer limits in place of a key's (see Limits). Sent with an API key, the request is held to the key's limits instead; the payer is whoever signs, usually the key's own wallet. An Authorization header that holds no valid key is refused 401, payment or not: it is never taken for a call with no key. Charged once. A request with a PAYMENT-SIGNATURE header is paid by that payment and nothing else. The wallet behind the key is not charged, even when it has a delegate, and a refused payment is answered with its reason: the API never pays through the delegate instead.

The requirements

A 402 lists the scheme's requirements after the delegate entry (alone, to a call with no API key: there is no wallet to name a delegate for), and alone, as x402 clients expect, in its PAYMENT-REQUIRED header (base64 of the JSON):
CodeJSON
amount is the model's job fee. payTo is the API itself: the job runs in a session the API owns, and your balance pays for it. extra.facilitatorAddress sends the settlement. The entry only changes when the fee does, so you can keep it and sign a fresh authorization for every call. A server that does not take per-call payments lists only the delegate entry. A call with no API key and no payment always gets that 402, with code payment_required: the x402 v2 handshake. A key whose wallet pays through a delegate gets no 402: its plain calls are served. To pay such a call per call anyway, send any unreadable PAYMENT-SIGNATURE (x) once: it is answered 400 invalid_payload with the current PAYMENT-REQUIRED, and nothing runs or is charged.

With the TypeScript SDK

@lightchainai/sdk (lightchain-sdk) does all of this in per-call mode (payment: "per-call"). Its fetch answers a 402 listing the requirements by signing the authorization and sending the call again with it, and never sends a transaction. It checks the entry against the network first, and refuses one that asks for more than maxPaymentWei.
CodeTYPESCRIPT
Without payment: "per-call" the SDK takes the delegate path and never signs a payment. In per-call mode apiKey is optional: without one, lc.fetch sends no Authorization header and lc.apiKey is a placeholder for the OpenAI SDK, which insists on one; with one, calls are held to that key's limits. The SDK never deposits in this mode: a call the balance can't cover fails with 402 insufficient_funds.

Sign and send

Copy the entry verbatim into the payment's accepted, and sign the authorization with the payer's key over the entry's domain:
CodeJAVASCRIPT
Then, with curl and no API key:
CodeBASH
To hold the calls to an API key's limits instead of the payer's, add -H "Authorization: Bearer $LIGHTCHAIN_API_KEY" to both. The answer is an ordinary completion. Its lightchain.tx_hash (and x-lightchain) is the settlement transaction, which submitted the job, and its PAYMENT-RESPONSE header carries the x402 settlement (base64 of {"success":true,"transaction":"0x...","network":"eip155:8200","payer":"0x...","amount":"..."}), amount being the fee debited. Streaming works the same way; the settlement happens before the first byte. One authorization pays for one call. Sign a new one, with a fresh nonce, for the next. If the job fails after the payment settled, the call answers 502 job_failed and is not retried on your payment; the protocol refunds a job its worker never answers to the payer's balance.

Pay-per-call codes

A refused payment keeps OpenAI's error shape, with the x402 reason as code. A 402 repeats accepts and PAYMENT-REQUIRED; a 400 carries PAYMENT-REQUIRED when the server takes per-call payments. When settlement was attempted, PAYMENT-RESPONSE says how it ended.
StatuscodeMeansWhat to do
402payment_requiredA call with no API key carried no payment.Pay the accepts entry: sign it and send it as PAYMENT-SIGNATURE.
402invalid_prepaid_debit_payload_expiredThe deadline has passed.Sign a new authorization.
402invalid_prepaid_debit_payload_nonce_usedThe authorization was already used.Sign a new one with a fresh nonce.
402invalid_prepaid_debit_payload_signatureThe signature does not recover to payer over this chain and JobRegistry: another key signed it, or it was signed for another network.Sign with the payer's key over the entry's domain.
402invalid_prepaid_debit_payload_over_capThe job's fee is above maxAmount.Set maxAmount to the entry's amount.
402insufficient_fundsThe payer's balance cannot cover the fee.deposit() from the payer's wallet.
402invalid_prepaid_debit_payload_facilitator_mismatch, invalid_prepaid_debit_payload_recipient_mismatchThe authorization names another facilitator or payTo than the entry.Copy both from the entry.
402invalid_prepaid_debit_facilitator_not_authorizedThe server's per-call setup is incomplete.Pay through the delegate meanwhile.
402invalid_transaction_stateThe chain refused the settlement.Retry shortly.
400invalid_payload, invalid_x402_version, invalid_network, invalid_payment_requirementsThe header is malformed, or its accepted is not the current entry (the fee changed).Rebuild it from the answer's PAYMENT-REQUIRED.
400unsupported_schemeThis server takes no per-call payments.Send the call without the header, on the delegate path.
401invalid_api_keyAn Authorization header holds no valid key, or a call with no key went to a server that takes no per-call payments.Send a valid key, or no Authorization header at all.
502unexpected_verify_error, unexpected_settle_errorThe API could not reach its facilitator, or the chain did not answer.Send the same header again: a payment that did settle is then refused as used, so it is never charged twice.

What your wallet signs

The delegate path asks your wallet only for the sign-in signature (when you manage keys) and the depositAndAuthorize transaction. Paying per call asks the payer for a deposit transaction once and an EIP-712 debit authorization per call, which a code-held key signs itself.