API reference · v1
Developers
Authentication
Every request carries an API key in the Authorization header. Keys are scoped to your contracts: a key can only submit to and read the contracts it was issued for.
header
Authorization: Bearer $CORSA_API_KEYSubmit
Submit a finalized PSBT (preferred) or a signed transaction against a contract. Validation happens here: anything that can be refused is refused now, never at mining time.
POST/v1/contracts/{contractId}/submissions
curl
curl -X POST https://api.corsa.example/v1/contracts/{contractId}/submissions \
-H "Authorization: Bearer $CORSA_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "psbt": "cHNidP8BAH..." }'202 Accepted
{
"submissionId": "sub_01J...",
"state": "accepted",
"weightUnits": 1532,
"window": { "startHeight": 921410, "endHeight": 921420 }
}Check status
States: accepted → queued → mining → delivered, or failed with a reason.
GET/v1/submissions/{submissionId}
Replace
Swap the staged transaction for a new one. Allowed until the delivery window opens.
PUT/v1/submissions/{submissionId}
Withdraw
Remove a submission. Allowed any time before delivery.
DELETE/v1/submissions/{submissionId}
Webhooks
Subscribe to state changes:
- submission.accepted
- submission.queued
- submission.mining
- submission.delivered
- submission.failed
submission.delivered
{
"type": "submission.delivered",
"submissionId": "sub_01J...",
"data": {
"txid": "4f2a...c91e",
"blockHeight": 921413,
"blockHash": "00000000000000000001a7...",
"coinbase": {
"txid": "9b0d...7f33",
"attribution": "corsa:delivery"
}
}
}Errors
Every rejection comes with a machine-readable reason code and a human-readable message.
422 Unprocessable
{
"error": {
"code": "input_already_spent",
"message": "An input of this transaction has been spent.",
"submissionId": "sub_01J..."
}
}