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):

FamilyBodyBackend 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

idstringrequired
The invoice ID (crypto-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" }.

status
seen — 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_required
Progress towards settlement.
already_processed
true when the invoice is already paid (no chain call made).

Errors

CodeHTTPWhen it happens
auth required401No valid session.
invoice not found404Unknown or foreign invoice.
inapp_rail_unsupported, invoice_not_inapp400Wrong rail/channel.
signature or signed_b64 required, bad signed_b64…, bad signature…400Solana: missing or undecodable body.
bad tx_hash…400EVM: not a transaction hash.
tx_mismatch422Solana 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_linked403Solana signed_b64 signed by a wallet that is not the linked one.
payer_check_unavailable503Linked-wallet check could not run; retry.
invoice_not_pending, invoice_already_funded409Nothing left to pay.
invoice_expired410Invoice expired.
submit_failed: …502Solana network rejected the broadcast.
billing_unavailable503Billing temporarily unavailable on this node; retry after Retry-After.
inapp not configured, rpc not configured503In-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: true and 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_linked on the invoice).