Blockchain network. Defaults to the environment's Base network when omitted ('base' on production, 'base-sepolia' on local/staging). Mainnet names sent to local/staging are coerced to their testnet counterpart (e.g. base → base-sepolia); testnet names sent to production are rejected with TESTNET_NOT_ALLOWED_IN_PRODUCTION.
orchestrationTypeenum"raw" · "coinbax"
Orchestration type: raw (direct blockchain) or coinbax (smart contract escrow)
templateIdstring (uuid)
Template ID from coinbax-library. The template will be fetched from the library service.
contractTemplateIdstring (uuid)
Contract template ID (alias for templateId, for backward compatibility)
templateobject
Complete template data embedded in request (optional, prefer using templateId instead)
TemplateDto
templateIdstringrequired
Template ID from coinbax-library
templateNamestringrequired
Template name
templateVersionstringrequired
Template version
controlsarray of TemplateControlDtorequired
Array of controls to execute
array of TemplateControlDto
idstringrequired
Control ID
typestringrequired
Control type (e.g., TimeDelay, TwoFactorAuth, ComplianceCheck)
Fee percentage in basis points (100 = 1%). Required for percentage type.
fixedFeeAmountnumber
Fixed fee amount in smallest currency unit. Required for fixed type.
tieredFeesarray of TieredFeeDto
Array of tiered fee configurations. Required for tiered type.
array of TieredFeeDto
minAmountnumberrequired
Minimum transaction amount for this tier
maxAmountnumberrequired
Maximum transaction amount for this tier
feePercentagenumberrequired
Fee percentage in basis points (100 = 1%)
feeWalletAddressstringrequired
Coinbax fee collection wallet address
currencystringrequired
Currency for fee collection
isActivebooleanrequired
Whether billing is active for this workspace
quoteIdstring (uuid)
FeeQuote id from a prior /transactions/quote call. Required when the workspace has BILLING_ENABLED=true (Phase 1 cutover).
signerTypestring
Which wallet signs this transaction. Omit it and Coinbax signs with a wallet it operates on your behalf. Send `external_wallet` when the sender signs with their own wallet, which is also the mode SafeSend and other consumer flows use. Gas-sponsored variants exist for senders who hold their own keys but should not pay gas; contact support before using them.
customerIdstring
Customer ID for external wallet transactions (Transmitter users)
idempotencyKeystring
Idempotency key to prevent duplicate transaction creation. If provided, a transaction with the same key will return the existing transaction instead of creating a new one.
Responses
201Transaction created successfully
rescindobject
Public-safe summary of the TimeDelay rescind config. Lets clients gate the Cancel/Rescind affordance without a second round-trip. Null when the transaction has no TimeDelay control (RAW orchestration, templates without a hold period). Absent from response on the list endpoint and on legacy api revisions.
TransactionRescindInfo
allowedbooleanrequired
Whether the sender is allowed to rescind/cancel the transaction during the hold window. Defaults to true when not explicitly set on the underlying control config.
deadlineobjectrequired
ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.
object
ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.
requiresReasonbooleanrequired
Whether the rescind endpoint requires a non-empty `reason` field in the request body.
notifyRecipientbooleanrequired
Whether the recipient is notified (e.g. via SMS) when a rescind succeeds.
Blockchain network. The set of accepted values mirrors `CreateTransactionDto.blockchainNetwork`, including the env-aware default ('base' on production, 'base-sepolia' on local/staging), non-prod coercion of mainnet names, and production rejection of testnet names.
orchestrationTypeenum"raw" · "coinbax"
Orchestration type for every leg.
signerTypestring
Which wallet signs this transaction. Omit it and Coinbax signs with a wallet it operates on your behalf. Send `external_wallet` when the sender signs with their own wallet, which is also the mode SafeSend and other consumer flows use. Gas-sponsored variants exist for senders who hold their own keys but should not pay gas; contact support before using them. Batches currently require the sender's own wallet.
templateIdstring (uuid)
Template ID from coinbax-library. Stored on the batch in B1; control execution against the template is wired in B2.
customerIdstring
Customer ID for external-wallet flows (Transmitter, SafeSend).
idempotencyKeystring
Idempotency key — if provided, an existing batch with the same key is returned instead of creating a new one.
metadataobject
Batch-level metadata (distinct from per-leg metadata).
object
Batch-level metadata (distinct from per-leg metadata).
templateobject
Embedded template (alternative to `templateId`, deprecated for consistency with `CreateTransactionDto`).
TemplateDto
templateIdstringrequired
Template ID from coinbax-library
templateNamestringrequired
Template name
templateVersionstringrequired
Template version
controlsarray of TemplateControlDtorequired
Array of controls to execute
array of TemplateControlDto
idstringrequired
Control ID
typestringrequired
Control type (e.g., TimeDelay, TwoFactorAuth, ComplianceCheck)
Returns a 120-second-TTL quote with platform fee, workspace fee, gas pass-through (if applicable), and total charged. Pass the returned `quoteId` to `POST /transactions` to lock the rate.
Returns public-safe summaries of each active control on a template. Use it to render pre-confirmation screens (for example, "what protects this payment") and to enforce client-side AmountLimit min/max. Sanitized: only a hand-picked subset of each control config is returned — policy/implementation fields are NOT exposed.
Query parameters
templateIdstringrequired
Responses
200Template config retrieved
templateIdstringrequired
Template UUID.
templateNamestringrequired
Template name (e.g. "Transmitter P2P").
templateVersionstringrequired
Template version string from the library (e.g. "1.0.0").
controlsarray of TemplateControlSummaryrequired
Active controls on the template, sanitized to a small set of public-safe fields per type. See TemplateControlSummary.
array of TemplateControlSummary
typestringrequired
Control type. Tolerates the upstream `ChainlysisSanctions` typo alongside the corrected `ChainalysisSanctions` for now (see PR #74).
phasestringrequired
Execution phase: PRE_ESCROW, POST_ESCROW, PRE_RELEASE, or POST_RELEASE.
namestringrequired
Human-readable control name (from the template, e.g. "Sanctions Screening").
isRequiredbooleanrequired
Whether this control is required (vs. optional — driven by `metadata.optional` on the template control).
minAmountnumber
AmountLimit: minimum allowed amount per send (inclusive).
maxAmountnumber
AmountLimit: maximum allowed amount per send (inclusive).
currencystring
AmountLimit: currency the limits are denominated in (e.g. "USD", "USDC").
TimeDelay: whether the sender can rescind/cancel during the hold window.
userConfigurableboolean
TimeDelay: whether the user can pick a delay value per transaction (vs. always the template default). When true, the frontend should render `options` as selectable presets. When false or absent, the frontend renders the template default as a read-only display.
optionsarray of string
TimeDelay: allowed preset values (when `userConfigurable` is true) using compact duration notation: `Nm` minutes, `Nh` hours, `Nd` days. Frontend parses and renders these as picker chips. Empty / absent means no template-defined presets — frontend may fall back to its own defaults.
array of string
string
sanctionsListsarray of string
ChainlysisSanctions / ChainalysisSanctions: which sanctions lists the screening checks (e.g. OFAC, SDN, EU).
array of string
string
checksSenderboolean
ChainlysisSanctions / ChainalysisSanctions: whether the sender wallet is screened.
checksRecipientboolean
ChainlysisSanctions / ChainalysisSanctions: whether the recipient wallet is screened.
verificationRequiredboolean
TwilioSMS: whether the SMS-verification step is mandatory (vs. lookup-only).
Public-safe summary of the TimeDelay rescind config. Lets clients gate the Cancel/Rescind affordance without a second round-trip. Null when the transaction has no TimeDelay control (RAW orchestration, templates without a hold period). Absent from response on the list endpoint and on legacy api revisions.
TransactionRescindInfo
allowedbooleanrequired
Whether the sender is allowed to rescind/cancel the transaction during the hold window. Defaults to true when not explicitly set on the underlying control config.
deadlineobjectrequired
ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.
object
ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.
requiresReasonbooleanrequired
Whether the rescind endpoint requires a non-empty `reason` field in the request body.
notifyRecipientbooleanrequired
Whether the recipient is notified (e.g. via SMS) when a rescind succeeds.
Marks a transaction in PENDING_USER_ACTION as FAILED with userCancelled=true. No on-chain action — funds were never escrowed. Use this when the user rejects the wallet popup and does not intend to retry; rejects with 400 if the transaction has already advanced to ESCROWED (use /refund or /rescind instead) or is already terminal. Requires `reverse:transactions` in v2.
Path parameters
idstringrequired
Request body
reasonstring
Optional human-readable reason for the cancellation. Surfaced in the transaction.failed webhook and stored on `metadata.cancelReason`.
Responses
200Transaction cancelled successfully
rescindobject
Public-safe summary of the TimeDelay rescind config. Lets clients gate the Cancel/Rescind affordance without a second round-trip. Null when the transaction has no TimeDelay control (RAW orchestration, templates without a hold period). Absent from response on the list endpoint and on legacy api revisions.
TransactionRescindInfo
allowedbooleanrequired
Whether the sender is allowed to rescind/cancel the transaction during the hold window. Defaults to true when not explicitly set on the underlying control config.
deadlineobjectrequired
ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.
object
ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.
requiresReasonbooleanrequired
Whether the rescind endpoint requires a non-empty `reason` field in the request body.
notifyRecipientbooleanrequired
Whether the recipient is notified (e.g. via SMS) when a rescind succeeds.
v1 called this `submit-escrow-hash`. Note coinbax-core proxies the v1 spelling and republishes it on the Workspace API, deliberately keeping that name rather than dragging a live consumer through a rename — so one operation has two spellings across the two surfaces.
Path parameters
idstringrequired
Request body
transactionHashstringrequired
Blockchain transaction hash from user wallet escrow deposit
escrowIdstring
Escrow ID returned by the smart contract (optional - will be detected from blockchain events if not provided)
Responses
200
rescindobject
Public-safe summary of the TimeDelay rescind config. Lets clients gate the Cancel/Rescind affordance without a second round-trip. Null when the transaction has no TimeDelay control (RAW orchestration, templates without a hold period). Absent from response on the list endpoint and on legacy api revisions.
TransactionRescindInfo
allowedbooleanrequired
Whether the sender is allowed to rescind/cancel the transaction during the hold window. Defaults to true when not explicitly set on the underlying control config.
deadlineobjectrequired
ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.
object
ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.
requiresReasonbooleanrequired
Whether the rescind endpoint requires a non-empty `reason` field in the request body.
notifyRecipientbooleanrequired
Whether the recipient is notified (e.g. via SMS) when a rescind succeeds.
v1 called this `submit-hash`; the verb already says you are submitting. Pairs with `escrow-hash` for COINBAX escrows.
Path parameters
idstringrequired
Request body
transactionHashstringrequired
Blockchain transaction hash from user wallet
Responses
200
rescindobject
Public-safe summary of the TimeDelay rescind config. Lets clients gate the Cancel/Rescind affordance without a second round-trip. Null when the transaction has no TimeDelay control (RAW orchestration, templates without a hold period). Absent from response on the list endpoint and on legacy api revisions.
TransactionRescindInfo
allowedbooleanrequired
Whether the sender is allowed to rescind/cancel the transaction during the hold window. Defaults to true when not explicitly set on the underlying control config.
deadlineobjectrequired
ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.
object
ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.
requiresReasonbooleanrequired
Whether the rescind endpoint requires a non-empty `reason` field in the request body.
notifyRecipientbooleanrequired
Whether the recipient is notified (e.g. via SMS) when a rescind succeeds.
Returns escrowed funds to the sender. Requires `reverse:transactions` in v2; v1 required `cancel:transactions`, which is not accepted here. `reverse:` does not inherit from the v1 scopes — they are siblings in the hierarchy — so a token minted for v1 must be re-issued.
Path parameters
idstringrequired
Request body
reasonstringrequired
Reason for refund
Responses
200Transaction refunded successfully
rescindobject
Public-safe summary of the TimeDelay rescind config. Lets clients gate the Cancel/Rescind affordance without a second round-trip. Null when the transaction has no TimeDelay control (RAW orchestration, templates without a hold period). Absent from response on the list endpoint and on legacy api revisions.
TransactionRescindInfo
allowedbooleanrequired
Whether the sender is allowed to rescind/cancel the transaction during the hold window. Defaults to true when not explicitly set on the underlying control config.
deadlineobjectrequired
ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.
object
ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.
requiresReasonbooleanrequired
Whether the rescind endpoint requires a non-empty `reason` field in the request body.
notifyRecipientbooleanrequired
Whether the recipient is notified (e.g. via SMS) when a rescind succeeds.
Coinbax submits the on-chain release for you. Absorbs v1 `complete` — same intent, different signer; the platform picks the on-chain path from which wallet signs and whether the hold window has elapsed, so you never name a contract function.
Call `POST /transactions/{id}/release/attest` instead if you want to broadcast yourself.
**Preconditions** — each mirrors an on-chain revert, so a failure here is the chain refusing, not a Coinbax policy:
- the escrow is still active (a released, refunded or rejected escrow reverts `EscrowNotActive` — one revert covers all three, so check `GET /transactions/{id}` rather than inferring the cause)
- the hold window has elapsed, i.e. `[releaseTime, ∞)`. Release opens **at** `releaseTime`; before that the chain reverts `ReleaseTimeNotReached`. Use `release-early` to waive the remainder.
- every required release control has passed. A failed required control auto-rejects the escrow and refunds the sender on-chain — do not then attempt a release.
Path parameters
idstringrequired
Request body
notestring
Optional completion note
Responses
200Released. Returns the full transaction, including its terminal status and the broadcast hash.
rescindobject
Public-safe summary of the TimeDelay rescind config. Lets clients gate the Cancel/Rescind affordance without a second round-trip. Null when the transaction has no TimeDelay control (RAW orchestration, templates without a hold period). Absent from response on the list endpoint and on legacy api revisions.
TransactionRescindInfo
allowedbooleanrequired
Whether the sender is allowed to rescind/cancel the transaction during the hold window. Defaults to true when not explicitly set on the underlying control config.
deadlineobjectrequired
ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.
object
ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.
requiresReasonbooleanrequired
Whether the rescind endpoint requires a non-empty `reason` field in the request body.
notifyRecipientbooleanrequired
Whether the recipient is notified (e.g. via SMS) when a rescind succeeds.
Submits a sender-signed early release through the Coinbax relayer, which pays the gas. Get the payload from `POST /transactions/{id}/release-early/attest`, have the sender wallet sign it, then post the signature here.
The signature is submitted **split** as `deadline`, `v`, `r`, `s` — not as a packed 65-byte hex string. Most wallet libraries return the packed form, so split it before calling.
**Preconditions** — each mirrors an on-chain revert:
- the escrow is still active (`EscrowNotActive`)
- the signature has not expired: valid while `block.timestamp <= deadline`, so equal is still valid (`ReleaseAuthExpired`)
- the recovered signer is the escrow sender (`OnlySenderCanRelease`)
- the workspace escrow has a relayer configured; without one the chain reverts `NotAuthorizedRelayer` and no funds move
Releasing early is final and forfeits the remaining hold window.
Path parameters
idstringrequired
Request body
deadlinestringrequired
Unix-seconds after which the authorization is expired.
vnumberrequired
y-parity of the signature (27 or 28).
rstringrequired
r component of the signature.
sstringrequired
s component of the signature.
Responses
200Released early. Returns the full transaction.
rescindobject
Public-safe summary of the TimeDelay rescind config. Lets clients gate the Cancel/Rescind affordance without a second round-trip. Null when the transaction has no TimeDelay control (RAW orchestration, templates without a hold period). Absent from response on the list endpoint and on legacy api revisions.
TransactionRescindInfo
allowedbooleanrequired
Whether the sender is allowed to rescind/cancel the transaction during the hold window. Defaults to true when not explicitly set on the underlying control config.
deadlineobjectrequired
ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.
object
ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.
requiresReasonbooleanrequired
Whether the rescind endpoint requires a non-empty `reason` field in the request body.
notifyRecipientbooleanrequired
Whether the recipient is notified (e.g. via SMS) when a rescind succeeds.
400Not an eligible escrow, wrong status, expired or malformed signature, or the signer is not the sender.
Response follows the unified success / data / meta / error envelope.
403Early release is not enabled for this workspace.
Response follows the unified success / data / meta / error envelope.
404Transaction not found
Response follows the unified success / data / meta / error envelope.
422ESCROW_NOT_VERIFIED: the platform could not confirm the escrow supports early release (a transient probe/RPC failure, or a non-WorkspaceEscrow contract). Retry shortly; if it persists, release after the hold window instead.
Response follows the unified success / data / meta / error envelope.
Runs the release controls and, only if they pass outright, returns the EIP-712 payload for the sender wallet to sign. No transaction, no gas, no funds moved.
Always returns **200** with a `mode`. `signature_required` carries `typedData`; the other three carry none, and none of them is an error condition in itself.
**The payload has no nonce, deliberately.** Replay protection is structural, not counter-based — see the response schema. Do not add your own replay guard.
Path parameters
idstringrequired
Responses
200`signature_required` with the payload to sign, or `permissionless` / `under_review` / `rejected` when no payload should be emitted.
modeobjectrequired
What to do next. Branch on this rather than on transaction state.
What to do next. Branch on this rather than on transaction state.
transactionIdstring (uuid)required
typedDataobject
Present only when `mode` is `signature_required`. Sign this with the sender wallet and submit the signature to the matching non-attest route.
**There is no nonce field, and that is deliberate.** Replay protection is structural rather than counter-based: `escrowId` is inside the signed struct, `verifyingContract` is this workspace's clone, `chainId` is in the domain, and a successful release clears the escrow's active flag so re-submitting the same signature reverts. Do not build your own replay guard, and do not look for a nonce to increment. `deadline` is the only time bound the signer controls.
Eip712ReleasePayloadDto
domainEip712DomainDtorequired
namestringrequired
versionstringrequired
chainIdnumberrequired
Chain the signature is bound to.
verifyingContractstringrequired
The escrow CLONE address for this workspace — not a shared implementation or factory address. Each workspace has its own clone and the contract recomputes its domain separator from its own address, so a signature cannot be replayed against another clone. Do not cache one value across workspaces.
typesobjectrequired
EIP-712 type definitions. Exactly one struct: `ReleaseEarly(bytes32 escrowId,uint256 deadline)`.
object
EIP-712 type definitions. Exactly one struct: `ReleaseEarly(bytes32 escrowId,uint256 deadline)`.
primaryTypestringrequired
messageEip712MessageDtorequired
escrowIdstringrequired
On-chain escrow id (bytes32).
deadlinestringrequired
Expiry as unix seconds, sent as a DECIMAL STRING. `uint256` exceeds Number.MAX_SAFE_INTEGER, so a JSON number would risk precision loss. The signature is valid while `block.timestamp <= deadline` — equal is still valid.
consequencestring
Present with `signature_required` on an early release. Show this to the sender before they sign — the hold window is a protection they are waiving.
releasableAtstring
Present when `mode` is `permissionless`: the hold window elapsed at this time, so the release needs no signature from anyone.
Runs the release controls and records the aggregate result on-chain, so your own release write does not revert on the escrow's control gate. **Never moves funds itself.**
Always returns **200** with a `mode` telling you what to do next — including `permissionless`, when the hold window has elapsed and the on-chain release needs no signature from anyone. That is not an error: asking for a payload you do not need is a well-formed question. A 400 here means the request itself was invalid (wrong status, no escrow), never "you did not need a signature".
Path parameters
idstringrequired
Responses
200One of four modes: `signature_required` (sign `typedData`), `permissionless` (no signature needed), `under_review` (a control has not resolved), `rejected` (a required control failed; the escrow was refunded on-chain).
modeobjectrequired
What to do next. Branch on this rather than on transaction state.
What to do next. Branch on this rather than on transaction state.
transactionIdstring (uuid)required
typedDataobject
Present only when `mode` is `signature_required`. Sign this with the sender wallet and submit the signature to the matching non-attest route.
**There is no nonce field, and that is deliberate.** Replay protection is structural rather than counter-based: `escrowId` is inside the signed struct, `verifyingContract` is this workspace's clone, `chainId` is in the domain, and a successful release clears the escrow's active flag so re-submitting the same signature reverts. Do not build your own replay guard, and do not look for a nonce to increment. `deadline` is the only time bound the signer controls.
Eip712ReleasePayloadDto
domainEip712DomainDtorequired
namestringrequired
versionstringrequired
chainIdnumberrequired
Chain the signature is bound to.
verifyingContractstringrequired
The escrow CLONE address for this workspace — not a shared implementation or factory address. Each workspace has its own clone and the contract recomputes its domain separator from its own address, so a signature cannot be replayed against another clone. Do not cache one value across workspaces.
typesobjectrequired
EIP-712 type definitions. Exactly one struct: `ReleaseEarly(bytes32 escrowId,uint256 deadline)`.
object
EIP-712 type definitions. Exactly one struct: `ReleaseEarly(bytes32 escrowId,uint256 deadline)`.
primaryTypestringrequired
messageEip712MessageDtorequired
escrowIdstringrequired
On-chain escrow id (bytes32).
deadlinestringrequired
Expiry as unix seconds, sent as a DECIMAL STRING. `uint256` exceeds Number.MAX_SAFE_INTEGER, so a JSON number would risk precision loss. The signature is valid while `block.timestamp <= deadline` — equal is still valid.
consequencestring
Present with `signature_required` on an early release. Show this to the sender before they sign — the hold window is a protection they are waiving.
releasableAtstring
Present when `mode` is `permissionless`: the hold window elapsed at this time, so the release needs no signature from anyone.
400Not an eligible escrow, wrong status, or no on-chain escrow.
Response follows the unified success / data / meta / error envelope.
404Transaction not found
Response follows the unified success / data / meta / error envelope.
422RELEASE_WINDOW_NOT_ELAPSED: the escrow is still inside its hold window, so releasing now requires the sender to waive the remainder. Use `release-early/attest` to get the payload for them to sign, or wait for the window to elapse.
Response follows the unified success / data / meta / error envelope.
curl -X POST https://api-staging.coinbax.com/api/v2/transactions/<id>/release/attest \
-H "Authorization: Bearer $ACCESS_TOKEN"
Allows the sender to cancel a transaction during the Payment Hold Period and have funds returned to their wallet. Only available if the TimeDelay control has allowSenderRescind enabled. Requires `reverse:transactions` in v2; v1 required `rescind:transactions`.
Path parameters
idstringrequired
Request body
reasonstring
Reason for rescinding the transaction (required if control config has rescindRequiresReason: true)
senderWalletstringrequired
Sender wallet address for authorization verification
Responses
200Transaction rescinded successfully, funds returned to sender
rescindobject
Public-safe summary of the TimeDelay rescind config. Lets clients gate the Cancel/Rescind affordance without a second round-trip. Null when the transaction has no TimeDelay control (RAW orchestration, templates without a hold period). Absent from response on the list endpoint and on legacy api revisions.
TransactionRescindInfo
allowedbooleanrequired
Whether the sender is allowed to rescind/cancel the transaction during the hold window. Defaults to true when not explicitly set on the underlying control config.
deadlineobjectrequired
ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.
object
ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.
requiresReasonbooleanrequired
Whether the rescind endpoint requires a non-empty `reason` field in the request body.
notifyRecipientbooleanrequired
Whether the recipient is notified (e.g. via SMS) when a rescind succeeds.