Skip to content

Compose offer authorizations before funding

POST
/v1/offer-funding-authorization-templates
curl --request POST \
--url https://api.digirare.com/v1/offer-funding-authorization-templates \
--header 'Content-Type: application/json' \
--header 'x-session-token: <x-session-token>' \
--data '{ "funding_psbt_hex": "example", "slot_vout": 1, "targets": [ { "utxo_txid": "example", "utxo_vout": 1 } ], "assets": [ "example" ], "expires_at": 1, "receive_address": "example", "delivery_mode": "detached", "fee_rate": 1 }'

Exact-offer authorization templates (1..7 targets) over one set-aside output (slot_vout) of an UNSIGNED offer funding template from POST /v1/offer-funding-templates, so one wallet review can sign the funding and these authorizations together (the fund-and-authorize-offers wallet bundle). Every funding input must be a witness input of the authenticated bidder, so signing cannot change the txid the authorizations spend. Each target is composed exactly as POST /v1/offers/{id}/exact-authorizations/batch composes it, at the one returned fee_rate, including the asset-UTXO depth rule; assets are the placement’s asset-scope targets and every target must be one of them. Nothing is stored, placed, or reserved, and authorization_id values are preview ids. After signing, place the offer with the signed funding (POST /v1/funded-offers), create the batch with fee_rate set to this response’s rate, and submit each signature whose expected_txid the batch reproduced; a template that no longer reproduces is signed again.

Media typeapplication/json
object
funding_psbt_hex
required

The unsigned funding.psbt_hex from POST /v1/offer-funding-templates.

string
/^(?:[0-9a-fA-F]{2})+$/
slot_vout
required
integer
targets
required
Array<object>
>= 1 items <= 7 items
object
utxo_txid
required
string
/^[0-9a-f]{64}$/
utxo_vout
required
integer
assets
required

The placement’s asset-scope targets, as POST /v1/funded-offers will receive them.

Array<string>
>= 1 items <= 100 items
expires_at
required
integer
receive_address
string
delivery_mode
string
Allowed values: detached attached
fee_rate
number
>= 0.1 <= 500

Successful composeOfferFundingAuthorizationTemplates response.

Media typeapplication/json
object
result
required

Exact-offer authorization templates over one set-aside output of an offer funding template that is not broadcast yet, for a wallet review that signs the funding and these authorizations together. Nothing is stored: after placing the offer with the signed funding, create the authorization batch with fee_rate set to this fee_rate; unchanged facts give byte-identical templates, so the signatures submit as they are. Each authorization_id here is a preview id, never a stored row.

object
protocol_version
required
string
Allowed value: exact_offer_v1
funding_txid
required

The funding template’s (unsigned, witness-only) txid.

string
funding_slot_id
required
string
fee_rate
required
number
target_count
required
number
authorizations
required
Array<object>
object
operation_id
required
string
protocol_version
required
string
Allowed value: exact_offer_v1
authorization_id
required
string
status
required
string
Allowed values: awaiting_bidder active
funding_slot_id
required
string
bidder
required
string
psbt_hex
required

Always the UNSIGNED settlement template, for both roles. The buyer’s input-0 signature is never served to the seller; the market merges it server-side when the seller submits input 1.

string
expected_txid
required
string
signing
required
object
psbt_hex
string
inputs_to_sign
required
Any of:
Array<number>
signer_address
string
sighash
string
Allowed values: ALL DEFAULT|ALL SINGLE|ANYONECANPAY
expected_txid
string
target
required
object
asset
required
string
quantity_raw
required

Counterparty atomic units. A string preserves integers beyond JSON’s safe numeric range; divisibility affects display, never this wire value.

string
/^[0-9]+$/
seller
required
string
outpoint
required
object
txid
required
string
vout
required
number
price_sats
required

Integer satoshis, exactly representable as a JSON number. Aggregated historical volume can exceed Bitcoin’s supply, so this is the safe JSON integer ceiling, not a single-transaction spending limit.

integer
<= 9007199254740991
seller_proceeds_sats
required

Integer satoshis, exactly representable as a JSON number. Aggregated historical volume can exceed Bitcoin’s supply, so this is the safe JSON integer ceiling, not a single-transaction spending limit.

integer
<= 9007199254740991
network_fee_sats
required

Integer satoshis, exactly representable as a JSON number. Aggregated historical volume can exceed Bitcoin’s supply, so this is the safe JSON integer ceiling, not a single-transaction spending limit.

integer
<= 9007199254740991
platform_fee_sats
required

Integer satoshis, exactly representable as a JSON number. Aggregated historical volume can exceed Bitcoin’s supply, so this is the safe JSON integer ceiling, not a single-transaction spending limit.

integer
<= 9007199254740991
platform_fee_internal_key

Hex x-only BIP86 internal key of the marketplace fee output, derived server-side from the fee allocation’s own index. The fee output is exactly the key-path-only P2TR of this key; a wallet that reads it checks that match and shows the fee payment either way. Absent when there is no key to vouch for (a pre-fee template or an unconfigured/rotated key).

string
prefunded_fee_sats
required

Integer satoshis, exactly representable as a JSON number. Aggregated historical volume can exceed Bitcoin’s supply, so this is the safe JSON integer ceiling, not a single-transaction spending limit.

integer
<= 9007199254740991
fee_rate
required
number
delivery
required
object
mode
required
string
Allowed values: detached attached
address
required
string
utxo_value_sats

Integer satoshis, exactly representable as a JSON number. Aggregated historical volume can exceed Bitcoin’s supply, so this is the safe JSON integer ceiling, not a single-transaction spending limit.

integer
<= 9007199254740991
signature_validity
required
object
marketplace_expires_at
required
number
bitcoin_expires_at
required
null
bitcoin_invalidation
required
object
type
required
string
Allowed value: spend_funding_outpoint
outpoint
required
object
txid
required
string
vout
required
number
fee_adjustment
Any of:
object
state
required
string
Allowed value: ready
signed_parent_fee_rate
required
number
current_target_fee_rate
required
number
parent_fee_sats
required

Integer satoshis, exactly representable as a JSON number. Aggregated historical volume can exceed Bitcoin’s supply, so this is the safe JSON integer ceiling, not a single-transaction spending limit.

integer
<= 9007199254740991
package_fee_sats
required

Integer satoshis, exactly representable as a JSON number. Aggregated historical volume can exceed Bitcoin’s supply, so this is the safe JSON integer ceiling, not a single-transaction spending limit.

integer
<= 9007199254740991
package_fee_rate
required
number
final_seller_proceeds_sats
required

Integer satoshis, exactly representable as a JSON number. Aggregated historical volume can exceed Bitcoin’s supply, so this is the safe JSON integer ceiling, not a single-transaction spending limit.

integer
<= 9007199254740991
cpfp
object
psbt_hex
required
string
expected_txid
required
string
signing
required
object
psbt_hex
string
inputs_to_sign
required
Any of:
Array<number>
signer_address
string
sighash
string
Allowed values: ALL DEFAULT|ALL SINGLE|ANYONECANPAY
expected_txid
string
expires_at
required
number
reserves_funding
boolean
requires_buyer_action
boolean
stored
required
boolean
reserves_funding
required
boolean
result_count
required
integer
Example
{
"result": {
"protocol_version": "exact_offer_v1",
"authorizations": [
{
"protocol_version": "exact_offer_v1",
"status": "awaiting_bidder",
"signing": {
"inputs_to_sign": "all",
"sighash": "ALL"
},
"delivery": {
"mode": "detached"
},
"signature_validity": {
"bitcoin_invalidation": {
"type": "spend_funding_outpoint"
}
},
"fee_adjustment": {
"state": "ready"
},
"cpfp": {
"signing": {
"inputs_to_sign": "all",
"sighash": "ALL"
}
},
"reserves_funding": false,
"requires_buyer_action": false
}
],
"stored": false,
"reserves_funding": false
}
}

Stable machine-readable failure

Media typeapplication/json
object
error
required
string
code
required
string
Allowed values: invalid_request unsupported_address_type unauthenticated forbidden not_found method_not_allowed state_changed expired invalid_transaction rate_limited internal_error upstream_unavailable service_unavailable checkout_changed target_unavailable signature_invalid template_mismatch mempool_rejected broadcast_unknown conflict_spend duplicate_funding_slot offer_selection_unavailable attached_delivery_single_item_only insufficient_funds insufficient_asset_balance price_below_minimum listing_price_above_maximum counter_price_invalid self_trade offer_capacity_full open_offer_limit policy_offer_refused
retryable
boolean
mempool_policy

On 422 mempool_rejected from a broadcast: which deterministic node policy refused the bytes. Retrying the same bytes fails the same way. fee_floor: re-quote at a higher fee_rate. chain_too_long: too many unconfirmed ancestors; wait for a confirmation, then retry. truc: a version-3 (TRUC) package rule, such as spending an unconfirmed version-3 output; wait for a confirmation, then retry.

string
Allowed values: fee_floor chain_too_long truc dust nonstandard
mempool_reason

The node’s own reject reason, on mempool_rejected (422) and on state_changed (409) when a broadcast lost to a conflicting or replacing spend.

string
wait_for_confirmation

Present and true when mempool_policy is chain_too_long or truc.

boolean
claims_released

On a checkout or accept completion refused as mempool_rejected: the journaled settlement ended and every listing, bid, and asset claim it held was released (its inputs were proven unspent). The quote or accept is replaced; request a new one.

boolean
refused_listings

Batch listing routes only: every refused item. The first sets the status and code.

Array<object>

One refused item in a batch refusal’s refused_listings array. Nothing in the batch was changed.

object
index
required
integer
listing_id
required
string
status
required
integer
code
required
string
error
required
string
key
additional properties
any
retry_after_seconds

On 429 rate_limited: the exact seconds until the oldest counted request leaves the window; a retry then is admitted (also sent as Retry-After). Limited writes are bucketed per route scope in exact sliding 60-second windows: by session address when a valid x-session-token is present, otherwise by IP, with a per-IP ceiling across sessions. Expensive writes: 20, ceiling 120. Signed completions: 120, ceiling 600. Session minting (/auth/*): 60 per IP. A request refused by any bucket is counted by none.

integer
>= 1
key
additional properties
any
Example
{
"code": "invalid_request",
"mempool_policy": "fee_floor"
}

Stable machine-readable failure

Media typeapplication/json
object
error
required
string
code
required
string
Allowed values: invalid_request unsupported_address_type unauthenticated forbidden not_found method_not_allowed state_changed expired invalid_transaction rate_limited internal_error upstream_unavailable service_unavailable checkout_changed target_unavailable signature_invalid template_mismatch mempool_rejected broadcast_unknown conflict_spend duplicate_funding_slot offer_selection_unavailable attached_delivery_single_item_only insufficient_funds insufficient_asset_balance price_below_minimum listing_price_above_maximum counter_price_invalid self_trade offer_capacity_full open_offer_limit policy_offer_refused
retryable
boolean
mempool_policy

On 422 mempool_rejected from a broadcast: which deterministic node policy refused the bytes. Retrying the same bytes fails the same way. fee_floor: re-quote at a higher fee_rate. chain_too_long: too many unconfirmed ancestors; wait for a confirmation, then retry. truc: a version-3 (TRUC) package rule, such as spending an unconfirmed version-3 output; wait for a confirmation, then retry.

string
Allowed values: fee_floor chain_too_long truc dust nonstandard
mempool_reason

The node’s own reject reason, on mempool_rejected (422) and on state_changed (409) when a broadcast lost to a conflicting or replacing spend.

string
wait_for_confirmation

Present and true when mempool_policy is chain_too_long or truc.

boolean
claims_released

On a checkout or accept completion refused as mempool_rejected: the journaled settlement ended and every listing, bid, and asset claim it held was released (its inputs were proven unspent). The quote or accept is replaced; request a new one.

boolean
refused_listings

Batch listing routes only: every refused item. The first sets the status and code.

Array<object>

One refused item in a batch refusal’s refused_listings array. Nothing in the batch was changed.

object
index
required
integer
listing_id
required
string
status
required
integer
code
required
string
error
required
string
key
additional properties
any
retry_after_seconds

On 429 rate_limited: the exact seconds until the oldest counted request leaves the window; a retry then is admitted (also sent as Retry-After). Limited writes are bucketed per route scope in exact sliding 60-second windows: by session address when a valid x-session-token is present, otherwise by IP, with a per-IP ceiling across sessions. Expensive writes: 20, ceiling 120. Signed completions: 120, ceiling 600. Session minting (/auth/*): 60 per IP. A request refused by any bucket is counted by none.

integer
>= 1
key
additional properties
any
Example
{
"code": "invalid_request",
"mempool_policy": "fee_floor"
}