Submit in-app transaction
Tell the billing backend about a signed in-app payment: relay a signed Solana transaction, or report the signature / hash of one the wallet already broadcast (Solana or EVM).
- Network
- Solana / Ethereum / BNB Smart Chain / Polygon (by the invoice's rail)
- Auth
- Console session cookie
The second half of the in-app flow, after build in-app transaction and the wallet's signature.
submit never marks the invoice paid. The deposit watcher detects the
transfer on chain and settles the invoice independently, after the rail's
confirmations. submit is a fast status check plus, for Solana, an
optional relay path. If the invoice is already settled you get 200 with
already_processed: true.
Tron is not paid in-app: tron-usdt is an on-chain transfer rail only
(inapp_build: false in GET /v1/billing/rails), and
submit answers 400 inapp_rail_unsupported for it.
Accepted bodies (send exactly one field):
| Family | Body | Backend action |
|---|---|---|
sol | { "signature": "<base58>" } | The wallet already sent the tx; syntax check only. |
sol | { "signed_b64": "<base64 signed tx>" } | Verifies the tx pays this invoice (recipient / token account, mint, amount ≥ remaining, reference key, valid signatures, only allowed programs), checks the fee payer is the linked Solana wallet, then broadcasts it. |
evm | { "tx_hash": "0x…64 hex" } | Read-only receipt check: sums Transfer logs of the rail's token to the deposit address. |
Parameters
Path parameters
idstringrequiredcrypto-inapp, owned by the session user).Response
Solana
submitted is true when the backend broadcast signed_b64, false for a
reported signature. Already settled: { "signature", "submitted": false, "already_processed": true, "status": "paid" }.
statusseen — a matching transfer of at least the remaining amount is in the receipt; pending — not mined yet (reason: not_mined) or node unavailable (reason: rpc_unavailable); mismatch — reason: tx_reverted, no_matching_transfer or underpaid (an underpayment is still credited as partial).confirmations / confirmations_requiredalready_processedtrue when the invoice is already paid (no chain call made).Errors
| Code | HTTP | When it happens |
|---|---|---|
auth required | 401 | No valid session. |
invoice not found | 404 | Unknown or foreign invoice. |
inapp_rail_unsupported, invoice_not_inapp | 400 | Wrong rail/channel. |
signature or signed_b64 required, bad signed_b64…, bad signature… | 400 | Solana: missing or undecodable body. |
bad tx_hash… | 400 | EVM: not a transaction hash. |
tx_mismatch | 422 | Solana signed_b64 does not pay this invoice. Body: { "error", "reason", "detail" } (e.g. no_payment_to_invoice, underpaid, unexpected_program, payer_mismatch, invalid_signature, address_lookup_tables_unsupported). Nothing is relayed. |
payer_not_linked | 403 | Solana signed_b64 signed by a wallet that is not the linked one. |
payer_check_unavailable | 503 | Linked-wallet check could not run; retry. |
invoice_not_pending, invoice_already_funded | 409 | Nothing left to pay. |
invoice_expired | 410 | Invoice expired. |
submit_failed: … | 502 | Solana network rejected the broadcast. |
billing_unavailable | 503 | Billing temporarily unavailable on this node; retry after Retry-After. |
inapp not configured, rpc not configured | 503 | In-app (or the relay path) disabled on this deployment. |
Notes
- Settlement is asynchronous. Watch the invoice's
SSE event stream for
invoice_paid, or poll get invoice. - Idempotent. Re-submitting is safe; a paid invoice returns
already_processed: trueand nothing is broadcast. - EVM sender is not re-checked on submit (the build step already enforced
the linked payer); every payment is reconciled after crediting and flagged if
it came from another wallet (
payer_linkedon the invoice).