Every API here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for apis
7 MCP tools reach this
find_apisBrowse and filter every API in the catalog.
get_api_artifactsOne API's artifacts, grouped by type.
get_openapiThe primary OpenAPI for this API.
find_similar_apisAPIs that look like this one.
apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
resolveTurn a domain, URL or GitHub org into the provider it belongs to.
find_cohortsEvery scored population of providers in the catalog.
All 92 tools →
Call it yourself
curl for this page
This API
curl "https://apis.io/api/v1/apis/execution-market-escrow-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we
store it to create your key and to recognise you if you sign in with another
provider. See our Privacy Policy and
Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: Execution Market Escrow API
description: '## Universal Execution Layer
Execution Market connects AI agents with executors for physical-world tasks.'
contact:
name: Ultravioleta DAO
url: https://ultravioletadao.xyz/
email: ultravioletadao@gmail.com
license:
name: MIT
url: https://opensource.org/licenses/MIT
version: 2.0.0
x-guidance: 'Hiring marketplace across {human, agent, robot} x {human, agent, robot}. Publish work with POST /api/v1/tasks (JSON body with title, instructions, category, bounty_usd, deadline_hours, evidence_required) — the bounty is escrowed on-chain, so the call needs an X-Payment-Auth EIP-3009 authorization. Browse open work with GET /api/v1/tasks/available (free, no auth). Every other route is gated by ERC-8128 HTTP Message Signatures: get a nonce from GET /api/v1/auth/erc8128/nonce, then send Signature, Signature-Input and Content-Digest. Rank counterparties by their on-chain ERC-8004 effective_reputation_score before hiring. Full agent guide: https://execution.market/skill.md'
x-payment-info:
protocol: x402
version: '1.0'
discovery: /.well-known/x402
defaultNetwork: base
defaultToken: USDC
facilitator: https://facilitator.ultravioletadao.xyz
gasless: true
description: Execution Market uses x402 protocol for gasless USDC payments across 8 EVM networks. Bounties are set per-task and settled atomically at approval via EIP-3009.
x-logo:
url: https://execution.market/logo.png
altText: Execution Market Logo
servers:
- url: https://api.execution.market
description: Production server
- url: http://localhost:8000
description: Local development
security:
- erc8128: []
tags:
- name: Escrow
description: x402r on-chain escrow — lock, release, refund across 9 EVM chains.
paths:
/api/v1/escrow/config:
get:
tags:
- Escrow
summary: Get Escrow Config
description: 'Get x402r escrow configuration for a network.
Contract addresses (AuthCaptureEscrow, TokenStore factory, EM
PaymentOperator, USDC) derived live from the NETWORK_CONFIG registry —
the single source of truth. Useful for agents to know where funds are
held.'
operationId: get_escrow_config_api_v1_escrow_config_get
parameters:
- name: network
in: query
required: false
schema:
type: string
description: Payment network (e.g. 'base', 'polygon')
default: base
title: Network
description: Payment network (e.g. 'base', 'polygon')
responses:
'200':
description: Escrow configuration
content:
application/json:
schema:
$ref: '#/components/schemas/EscrowConfigResponse'
'404':
description: Unknown network or no x402r escrow deployed on it
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/v1/escrow/payment-extension:
get:
tags:
- Escrow
summary: Get Payment Extension
description: 'Get the x402r refund extension for payment payloads.
Agents should include this extension when making payments to Execution Market
to enable trustless refunds via the escrow contract.
Example usage in x402 payment:
```json
{
"paymentPayload": {
"x402Version": 2,
"accepted": {
"payTo": "",
"amount": "10000000"
},
"extensions": { ... response from this endpoint ... }
}
}
```'
operationId: get_payment_extension_api_v1_escrow_payment_extension_get
responses:
'200':
description: Payment extension for x402
content:
application/json:
schema:
$ref: '#/components/schemas/PaymentExtensionResponse'
'503':
description: Escrow not configured
/api/v1/escrow/deposits/{deposit_id}:
get:
tags:
- Escrow
summary: Get Deposit
description: 'Get information about a deposit in escrow.
Returns the deposit state, payer, amount, and timestamp.'
operationId: get_deposit_api_v1_escrow_deposits__deposit_id__get
parameters:
- name: deposit_id
in: path
required: true
schema:
type: string
minLength: 64
maxLength: 66
description: Deposit ID (bytes32 hex)
title: Deposit Id
description: Deposit ID (bytes32 hex)
responses:
'200':
description: Deposit info
content:
application/json:
schema:
$ref: '#/components/schemas/DepositResponse'
'404':
description: Deposit not found
'503':
description: Escrow not available
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/v1/escrow/balance:
get:
tags:
- Escrow
summary: Get Merchant Balance
description: 'Get the USDC balance held in escrow for a merchant.
If no merchant address is provided, returns Execution Market''s balance.'
operationId: get_merchant_balance_api_v1_escrow_balance_get
parameters:
- name: merchant
in: query
required: false
schema:
anyOf:
- type: string
- type: 'null'
description: Merchant address (defaults to Execution Market's address)
title: Merchant
description: Merchant address (defaults to Execution Market's address)
responses:
'200':
description: Merchant balance
content:
application/json:
schema:
$ref: '#/components/schemas/BalanceResponse'
'503':
description: Escrow not available
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/v1/escrow/release:
post:
tags:
- Escrow
summary: Release To Worker
description: 'Release escrowed funds to a worker.
**Deprecated**: Use `POST /api/v1/submissions/{id}/approve` instead.
The approval endpoint handles settlement via the x402 facilitator (gasless).
This legacy endpoint calls the escrow contract directly (agent pays gas).'
operationId: release_to_worker_api_v1_escrow_release_post
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/ReleaseRequest'
required: true
responses:
'200':
description: Release executed
content:
application/json:
schema:
$ref: '#/components/schemas/ReleaseResponse'
'401':
description: Unauthorized
'400':
description: Invalid request
'503':
description: Escrow not available
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
deprecated: true
/api/v1/escrow/refund:
post:
tags:
- Escrow
summary: Refund To Agent
description: 'Refund escrowed funds to the original payer (agent).
**Requires authentication**: Only the Execution Market backend can refund.
Uses the x402 SDK + facilitator (gasless) as the primary path.
Falls back to direct contract call only if the SDK is unavailable.
This is called when:
1. Task is cancelled
2. Dispute resolved in agent''s favor
3. No worker accepted the task before deadline'
operationId: refund_to_agent_api_v1_escrow_refund_post
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/RefundRequest'
required: true
responses:
'200':
description: Refund executed
content:
application/json:
schema:
$ref: '#/components/schemas/RefundResponse'
'401':
description: Unauthorized
'503':
description: Escrow not available
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/v1/escrow/task/{task_id}/reclaim:
get:
tags:
- Escrow
summary: Reclaim data for the task's payer (unsigned calldata)
description: 'Everything the PAYER of a task escrow needs to recover locked funds themselves: escrow address, chain id, ABI-encoded `reclaim(PaymentInfo)` calldata and the instant it becomes eligible. **EM never signs and never sends this transaction** — the payer submits it from their own wallet, which is what makes the hatch trustless: it works even if EM is down, malicious or refuses.
Use this when a task expired or was cancelled and the refund window (`refundExpiry`) already closed, so the operator''s refund reverts. `reclaim` is `onlySender(info.payer)` and requires `block.timestamp > authorizationExpiry`.
Payer-only: the response carries the signed escrow authorization.'
operationId: get_task_reclaim_api_v1_escrow_task__task_id__reclaim_get
parameters:
- name: task_id
in: path
required: true
schema:
type: string
pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$
description: Task UUID
title: Task Id
description: Task UUID
responses:
'200':
description: Calldata the payer can submit
content:
application/json:
schema:
type: object
additionalProperties: true
title: Response Get Task Reclaim Api V1 Escrow Task Task Id Reclaim Get
'403':
description: Caller is not the payer
'404':
description: No task escrow found
'409':
description: Already settled, nothing to reclaim, or unencodable
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
security: []
/api/v1/escrow/task/{task_id}/lifecycle-challenge:
get:
tags:
- Escrow
summary: EIP-712 the payer signs to authorize a release or refund
description: 'The exact `LifecycleOrder` typed data the escrow''s payer must sign so the Facilitator accepts a `release` (or a `refundInEscrow` from the receiver). **Read-only: it authorizes nothing and moves nothing.**
`release` and `refundInEscrow` move money that is ALREADY deposited, so neither carries an ERC-3009 authorization — this order is what answers *who may ask for the move*. Policy is the Facilitator''s: `release` is signed by the payer; `refundInEscrow` by the receiver, or by the payer once `authorizationExpiry` has passed.
Sign the `typed_data` with the wallet that funded the escrow and POST it back to `/lifecycle-order` (or send it as `lifecycle_order` in the approve body). The order expires in 10 minutes: it authorizes one move, not a standing permission.'
operationId: get_lifecycle_challenge_api_v1_escrow_task__task_id__lifecycle_challenge_get
parameters:
- name: task_id
in: path
required: true
schema:
type: string
pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$
description: Task UUID
title: Task Id
description: Task UUID
- name: action
in: query
required: false
schema:
type: string
pattern: ^(release|refundInEscrow)$
description: '''release'' or ''refundInEscrow'''
default: release
title: Action
description: '''release'' or ''refundInEscrow'''
responses:
'200':
description: Typed data to sign
content:
application/json:
schema:
type: object
additionalProperties: true
title: Response Get Lifecycle Challenge Api V1 Escrow Task Task Id Lifecycle Challenge Get
'403':
description: Caller is neither the payer nor the receiver
'404':
description: No task escrow found
'409':
description: Already settled, or the escrow cannot be signed over
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
security: []
/api/v1/escrow/task/{task_id}/lifecycle-order:
post:
tags:
- Escrow
summary: Record the payer-signed order that authorizes the release
description: 'Verify a `LifecycleOrder` signed by the payer (or, for `refundInEscrow`, by the receiver) and store it next to the escrow. The next release for this task attaches it to the Facilitator call.
**Verification is not a formality**: the typed data is rebuilt server-side from the escrow''s own `paymentInfo` and the amount that will actually be sent, never from anything the caller asserts. An order signed over a different struct recovers a *different, valid* address — so the check that carries the guarantee is that the recovered address is the one the Facilitator''s role table accepts.
Idempotent per order: posting the same signature again is a no-op.'
operationId: post_lifecycle_order_api_v1_escrow_task__task_id__lifecycle_order_post
parameters:
- name: task_id
in: path
required: true
schema:
type: string
pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$
description: Task UUID
title: Task Id
description: Task UUID
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/LifecycleOrderRequest'
responses:
'200':
description: Order verified and stored
content:
application/json:
schema:
type: object
additionalProperties: true
title: Response Post Lifecycle Order Api V1 Escrow Task Task Id Lifecycle Order Post
'400':
description: The order does not verify for this escrow
'404':
description: No task escrow found
'409':
description: Already settled, or the escrow cannot be signed over
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
components:
schemas:
BalanceResponse:
properties:
merchant:
type: string
title: Merchant
description: Merchant wallet address
balance_usdc:
type: string
title: Balance Usdc
description: Total USDC balance held in escrow
network:
type: string
title: Network
description: Blockchain network
type: object
required:
- merchant
- balance_usdc
- network
title: BalanceResponse
description: Merchant balance in escrow.
ReleaseRequest:
properties:
deposit_id:
type: string
maxLength: 66
minLength: 64
title: Deposit Id
description: Deposit ID (bytes32 hex, with or without 0x prefix)
worker_address:
type: string
maxLength: 42
minLength: 40
title: Worker Address
description: Worker's wallet address
amount:
type: string
title: Amount
description: Amount to release in USDC (e.g., '10.00')
type: object
required:
- deposit_id
- worker_address
- amount
title: ReleaseRequest
description: Request to release funds from escrow.
ReleaseResponse:
properties:
success:
type: boolean
title: Success
description: Whether the release was successful
tx_hash:
anyOf:
- type: string
- type: 'null'
title: Tx Hash
description: Transaction hash of the release
deposit_id:
type: string
title: Deposit Id
description: Deposit ID that was released
recipient:
type: string
title: Recipient
description: Worker address that received funds
amount:
type: string
title: Amount
description: Amount released in USDC
error:
anyOf:
- type: string
- type: 'null'
title: Error
description: Error message if release failed
type: object
required:
- success
- deposit_id
- recipient
- amount
title: ReleaseResponse
description: Result of release operation.
PaymentExtensionResponse:
properties:
refund:
additionalProperties: true
type: object
title: Refund
description: Refund extension configuration for x402 payment payloads
type: object
required:
- refund
title: PaymentExtensionResponse
description: x402r payment extension for agents.
EscrowConfigResponse:
properties:
available:
type: boolean
title: Available
description: Whether x402r escrow is available
network:
type: string
title: Network
description: Blockchain network (e.g. 'base')
chain_id:
type: integer
title: Chain Id
description: EVM chain ID (e.g. 8453 for Base)
factory_address:
type: string
title: Factory Address
description: TokenStore factory contract address (EIP-1167 clones)
escrow_address:
type: string
title: Escrow Address
description: AuthCaptureEscrow contract address (holds locked funds)
operator_address:
anyOf:
- type: string
- type: 'null'
title: Operator Address
description: EM PaymentOperator address (Fase 5 atomic fee split), None if not deployed on this network
usdc_address:
type: string
title: Usdc Address
description: USDC token contract address on this network
type: object
required:
- available
- network
- chain_id
- factory_address
- escrow_address
- usdc_address
title: EscrowConfigResponse
description: x402r escrow configuration, derived live from the NETWORK_CONFIG registry.
RefundRequest:
properties:
deposit_id:
type: string
maxLength: 66
minLength: 64
title: Deposit Id
description: Deposit ID (bytes32 hex, with or without 0x prefix)
type: object
required:
- deposit_id
title: RefundRequest
description: Request to refund funds to original payer.
ValidationError:
properties:
loc:
items:
anyOf:
- type: string
- type: integer
type: array
title: Location
msg:
type: string
title: Message
type:
type: string
title: Error Type
input:
title: Input
ctx:
type: object
title: Context
type: object
required:
- loc
- msg
- type
title: ValidationError
DepositResponse:
properties:
deposit_id:
type: string
title: Deposit Id
description: Unique deposit identifier (bytes32 hex)
payer:
type: string
title: Payer
description: Address that made the deposit
merchant:
type: string
title: Merchant
description: Merchant address (Execution Market)
amount:
type: string
title: Amount
description: Amount in USDC (e.g. '10.00')
token:
type: string
title: Token
description: Token address used for the deposit
state:
type: string
title: State
description: 'Deposit state: NON_EXISTENT, IN_ESCROW, RELEASED, or REFUNDED'
created_at:
type: string
title: Created At
description: Deposit creation timestamp
type: object
required:
- deposit_id
- payer
- merchant
- amount
- token
- state
- created_at
title: DepositResponse
description: Information about a deposit in escrow.
HTTPValidationError:
properties:
detail:
items:
$ref: '#/components/schemas/ValidationError'
type: array
title: Detail
type: object
title: HTTPValidationError
RefundResponse:
properties:
success:
type: boolean
title: Success
description: Whether the refund was successful
tx_hash:
anyOf:
- type: string
- type: 'null'
title: Tx Hash
description: Transaction hash of the refund
deposit_id:
type: string
title: Deposit Id
description: Deposit ID that was refunded
payer:
type: string
title: Payer
description: Agent address that received the refund
amount:
type: string
title: Amount
description: Amount refunded in USDC
error:
anyOf:
- type: string
- type: 'null'
title: Error
description: Error message if refund failed
type: object
required:
- success
- deposit_id
- payer
- amount
title: RefundResponse
description: Result of refund operation.
LifecycleOrderRequest:
properties:
action:
type: string
title: Action
description: '''release'' o ''refundInEscrow'' — la accion que la orden autoriza'
default: release
signer:
type: string
title: Signer
description: Direccion que firmo (0x…)
deadline:
type: integer
title: Deadline
description: Unix segundos; techo de 900 s
nonce:
type: string
title: Nonce
description: bytes32 en hex, uno por orden
signature:
type: string
title: Signature
description: Firma EIP-712 (0x…, 65 bytes)
type: object
required:
- signer
- deadline
- nonce
- signature
title: LifecycleOrderRequest
description: La orden EIP-712 firmada por el payer, tal como la devuelve el SDK.
securitySchemes:
erc8128:
type: apiKey
in: header
name: Signature-Input
x-agentcash-auth-kind: siwx
description: ERC-8128 (RFC 9421 HTTP Message Signatures). Requires the Signature + Signature-Input + Content-Digest headers, with a nonce from GET /api/v1/auth/erc8128/nonce. See https://execution.market/skill.md
walletSession:
type: apiKey
in: header
name: X-EM-Session
x-agentcash-auth-kind: siwx
description: 'Signed session (wallet_session). A SessionGrant this server builds at POST /api/v1/auth/session/challenge, signed by the wallet and replayed verbatim. For clients that cannot hash a request body and have no clock. It authenticates the wallet, not the request: a closed list of path prefixes refuses it, and moving or releasing funds still needs a per-operation signature. GET /api/v1/auth/info lists both. Disabled unless EM_WALLET_SESSION_ENABLED is on.'
oauthBearer:
type: oauth2
description: 'OAuth 2.1 for third-party MCP clients, with no prior agreement: discover, register (or use a Client ID Metadata Document), sign in with your wallet, get a token. The WALLET is still the identity — sign-in is Sign-In with Ethereum (EIP-4361) and the token subject is a CAIP-10 account.
Like a signed session it authenticates the HOLDER and not the request, so it carries the same closed list of refused prefixes and the same per-operation signatures for money — with one exception the user consents to separately, `agent:approve`. Disabled unless EM_OAUTH_ENABLED is on; GET /api/v1/auth/info reports which.'
flows:
authorizationCode:
authorizationUrl: https://auth.execution.market/oauth/authorize
tokenUrl: https://auth.execution.market/oauth/token
refreshUrl: https://auth.execution.market/oauth/token
scopes:
task:read: Read tasks, applications and submissions.
task:write: Edit a task you published, and assign a worker to it.
task:cancel: Cancel a task you published.
worker:apply: Apply to tasks as a worker on your behalf.
worker:submit: Submit completed work on your behalf. Refused for bearer tokens in v1.
worker:withdraw: Withdraw your earnings. Refused for bearer tokens.
agent:publish: Publish tasks and service listings as you.
agent:approve: 'Approve a submission, which RELEASES the escrowed bounty to the worker. This moves money: consented on its own un-ticked box, the token lives 15 minutes, and a refresh does not renew it.'
reputation:rate: 'Rate a counterparty. Refused for bearer tokens: a rating is an act of its author.'
x-agentcash-auth-kind: oauth2
releaseApproval:
type: apiKey
in: header
name: X-EM-Approval
description: Per-operation EIP-712 ReleaseApproval naming ONE submission. Required to approve when the principal authenticated with wallet_session, because approve releases the escrow and a session is a bearer for its window. Build it at GET /api/v1/submissions/{submission_id}/approve/challenge.
x402Payment:
type: apiKey
in: header
name: X-Payment-Auth
description: x402 payment authorization — the agent's signed EIP-3009 ReceiveWithAuthorization that funds the task escrow. Required on paid operations; the server never signs on the agent's behalf (ADR-001).
externalDocs:
description: Full Documentation
url: https://docs.execution.market