Ultravioleta DAO Submissions API

Evidence submissions from workers — upload proof, check status.

Operations 5

GET /api/v1/tasks/{task_id}/submissions Get Task Submissions #
GET /api/v1/submissions/{submission_id}/approve/challenge Approve Submission Challenge #
POST /api/v1/submissions/{submission_id}/approve Approve Submission #
POST /api/v1/submissions/{submission_id}/reject Reject Submission #
POST /api/v1/submissions/{submission_id}/request-more-info Request More Information #

Documentation

Specifications

Other Resources

Work with this as data

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-submissions-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 Specification

execution-market-submissions-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Execution Market Submissions 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: Submissions
  description: Evidence submissions from workers — upload proof, check status.
paths:
  /api/v1/tasks/{task_id}/submissions:
    get:
      tags:
      - Submissions
      summary: Get Task Submissions
      description: Retrieve all submissions for a specific task with AI verification scores
      operationId: get_submissions_api_v1_tasks__task_id__submissions_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: UUID of the task
          title: Task Id
        description: UUID of the task
      responses:
        '200':
          description: Submissions retrieved successfully with AI pre-check scores
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubmissionListResponse'
        '401':
          description: Unauthorized - invalid or missing API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Not authorized to view submissions for this task
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Task not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
      security: []
  /api/v1/submissions/{submission_id}/approve/challenge:
    get:
      tags:
      - Submissions
      summary: Approve Submission Challenge
      description: 'Return the EIP-712 `ReleaseApproval` a signed-session principal must sign to approve this submission, and the header to send it back in (`X-EM-Approval`). Read-only: it approves nothing and releases nothing.


        Approve is the step that RELEASES the escrow, and it does so with no signature of its own. A session grant is a bearer for its window, so the bridge refuses approve on the session alone and asks for a second signature that names THIS submission — copying a session header out of a log must not buy the ability to pay out a worker.


        Principals authenticated with ERC-8128 do not need this: their request is already signed per-request.'
      operationId: get_approve_challenge_api_v1_submissions__submission_id__approve_challenge_get
      parameters:
      - name: submission_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: UUID of the submission
          title: Submission Id
        description: UUID of the submission
      responses:
        '200':
          description: The ReleaseApproval typed data to sign
          content:
            application/json:
              schema: {}
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Not authorized to approve this submission
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Submission not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /api/v1/submissions/{submission_id}/approve:
    post:
      tags:
      - Submissions
      summary: Approve Submission
      description: Approve a worker's submission and trigger payment settlement
      operationId: approve_submission_api_v1_submissions__submission_id__approve_post
      parameters:
      - name: submission_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: UUID of the submission
          title: Submission Id
        description: UUID of the submission
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ApprovalRequest'
      responses:
        '200':
          description: Submission approved and payment released to worker
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '401':
          description: Unauthorized - invalid or missing API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Not authorized to approve this submission
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Submission not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: Submission already processed or task not in valid state
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '502':
          description: Payment settlement failed - submission not approved
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /api/v1/submissions/{submission_id}/reject:
    post:
      tags:
      - Submissions
      summary: Reject Submission
      description: Reject a worker's submission and return task to available pool
      operationId: reject_submission_api_v1_submissions__submission_id__reject_post
      parameters:
      - name: submission_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: UUID of the submission
          title: Submission Id
        description: UUID of the submission
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RejectionRequest'
      responses:
        '200':
          description: Submission rejected and task returned to available pool
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '401':
          description: Unauthorized - invalid or missing API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Not authorized to reject this submission
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Submission not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: Submission already processed with different verdict
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /api/v1/submissions/{submission_id}/request-more-info:
    post:
      tags:
      - Submissions
      summary: Request More Information
      description: Request additional evidence or clarification from the assigned worker
      operationId: request_more_info_submission_api_v1_submissions__submission_id__request_more_info_post
      parameters:
      - name: submission_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: UUID of the submission
          title: Submission Id
        description: UUID of the submission
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RequestMoreInfoRequest'
      responses:
        '200':
          description: Additional information requested from worker
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '401':
          description: Unauthorized - invalid or missing API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Not authorized to update this submission
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Submission not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: Submission already processed with final verdict
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
components:
  schemas:
    SubmissionListResponse:
      properties:
        submissions:
          items:
            $ref: '#/components/schemas/SubmissionResponse'
          type: array
          title: Submissions
          description: List of submission objects
        count:
          type: integer
          title: Count
          description: Total number of submissions
      type: object
      required:
      - submissions
      - count
      title: SubmissionListResponse
      description: Response model for submission list.
    RequestMoreInfoRequest:
      properties:
        notes:
          type: string
          maxLength: 1000
          minLength: 5
          title: Notes
          description: Required clarification request
      additionalProperties: false
      type: object
      required:
      - notes
      title: RequestMoreInfoRequest
      description: Request model for requesting more info on a submission.
    LifecycleOrderPayload:
      properties:
        action:
          type: string
          enum:
          - release
          - refundInEscrow
          title: Action
          default: release
        signer:
          type: string
          title: Signer
          description: Address that signed the order (0x…)
        deadline:
          type: integer
          title: Deadline
          description: Unix seconds; the Facilitator caps it at 900
        nonce:
          type: string
          title: Nonce
          description: bytes32 hex, one per order
        signature:
          type: string
          title: Signature
          description: EIP-712 signature (0x…)
      additionalProperties: false
      type: object
      required:
      - signer
      - deadline
      - nonce
      - signature
      title: LifecycleOrderPayload
      description: 'The EIP-712 escrow lifecycle order, signed by the PAYER.


        ``release`` moves money that is already deposited, so it carries no

        ERC-3009 authorization — this order is what answers *who may ask for the

        move*. The Facilitator accepts the payer (or the operator owner, which is

        EM''s treasury cold wallet and never signs), so on a release this is the

        publisher''s own signature, and EM only transports it.


        Get the exact typed data from

        ``GET /api/v1/escrow/task/{task_id}/lifecycle-challenge``. It expires in 10

        minutes: it authorizes ONE move, not a standing permission.'
    ErrorResponse:
      properties:
        error:
          type: string
          title: Error
          description: Error code (e.g. TASK_NOT_FOUND, UNAUTHORIZED)
        message:
          type: string
          title: Message
          description: Human-readable error message
        details:
          anyOf:
          - additionalProperties: true
            type: object
          - type: 'null'
          title: Details
          description: Additional error context
      type: object
      required:
      - error
      - message
      title: ErrorResponse
      description: Error response model.
    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
    ApprovalRequest:
      properties:
        notes:
          anyOf:
          - type: string
            maxLength: 1000
          - type: 'null'
          title: Notes
          description: Optional notes about the approval
        rating_score:
          anyOf:
          - type: integer
            maximum: 100.0
            minimum: 0.0
          - type: 'null'
          title: Rating Score
          description: 'DEPRECATED (2026-08-28) — ACCEPTED AND IGNORED. It used to emit the publisher→executor rating through the legacy path, which puts the FACILITATOR on record as its on-chain author. That no longer blocks your own signed rating: dedup counts authors, not parties, so a legacy rating is superseded instead of 409''d, and the 409 ''already rated in this direction'' now means only that YOU already signed it — it names the author inline (`authored_by: <wallet> (rater)`). Approving pays; rate separately with POST /reputation/relay/{prepare,submit} (signed by you, gasless) or the legacy /reputation/workers/rate if you cannot sign. Still accepted so no client breaks.'
          deprecated: true
        lifecycle_order:
          anyOf:
          - $ref: '#/components/schemas/LifecycleOrderPayload'
          - type: 'null'
          description: EIP-712 escrow lifecycle order signed by the payer, authorizing this release. Get the typed data from GET /api/v1/escrow/task/{task_id}/lifecycle-challenge.
      additionalProperties: false
      type: object
      title: ApprovalRequest
      description: Request model for approving a submission.
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          type: array
          title: Detail
      type: object
      title: HTTPValidationError
    SubmissionResponse:
      properties:
        id:
          type: string
          title: Id
          description: Unique submission identifier (UUID)
        task_id:
          type: string
          title: Task Id
          description: Associated task ID
        executor_id:
          type: string
          title: Executor Id
          description: Worker's executor ID
        status:
          type: string
          title: Status
          description: Current verdict status (pending, accepted, rejected, more_info_requested, disputed)
        pre_check_score:
          anyOf:
          - type: number
          - type: 'null'
          title: Pre Check Score
          description: AI pre-check score (0.0-1.0) if evidence was auto-verified
        submitted_at:
          type: string
          format: date-time
          title: Submitted At
          description: Submission timestamp (ISO 8601)
        evidence:
          anyOf:
          - additionalProperties: true
            type: object
          - type: 'null'
          title: Evidence
          description: Submitted evidence data (photos, text, documents)
        agent_verdict:
          anyOf:
          - type: string
          - type: 'null'
          title: Agent Verdict
          description: Agent's verdict on the submission
        agent_notes:
          anyOf:
          - type: string
          - type: 'null'
          title: Agent Notes
          description: Agent's notes explaining the verdict
        verified_at:
          anyOf:
          - type: string
            format: date-time
          - type: 'null'
          title: Verified At
          description: Timestamp when submission was verified
        ai_verification_result:
          anyOf:
          - additionalProperties: true
            type: object
          - type: 'null'
          title: Ai Verification Result
          description: AI verification analysis from Phase B (contains explanation, decision, confidence, task_specific_checks). Null until async AI verification completes.
        arbiter_grade:
          anyOf:
          - type: string
          - type: 'null'
          title: Arbiter Grade
          description: 'Letter grade from arbiter evaluation: A, B, C, D, or F'
        arbiter_summary:
          anyOf:
          - type: string
          - type: 'null'
          title: Arbiter Summary
          description: Human-readable arbiter verdict summary (max 500 chars)
        arbiter_verdict:
          anyOf:
          - type: string
          - type: 'null'
          title: Arbiter Verdict
          description: 'Ring 2 arbiter decision: pass, fail, inconclusive, or skipped. Null until Phase B verification completes.'
        arbiter_commitment_hash:
          anyOf:
          - type: string
          - type: 'null'
          title: Arbiter Commitment Hash
          description: Commitment hash the arbiter attested to (cryptographic audit trail)
        arbiter_evidence_hash:
          anyOf:
          - type: string
          - type: 'null'
          title: Arbiter Evidence Hash
          description: Hash of the evidence bundle the arbiter evaluated
        arbiter_verdict_signature:
          anyOf:
          - additionalProperties: true
            type: object
          - type: 'null'
          title: Arbiter Verdict Signature
          description: EIP-191 attestation over the commitment hash ({signature, signer_address, scheme}). Null when arbiter signing is not enabled.
        arbiter_tier:
          anyOf:
          - type: string
          - type: 'null'
          title: Arbiter Tier
          description: 'Inference tier that decided this submission: cheap (no LLM — Ring 1 only), standard (1 LLM call) or max (2 calls + consensus).'
        arbiter_score:
          anyOf:
          - type: number
          - type: 'null'
          title: Arbiter Score
          description: Aggregate score (0-1) the arbiter produced.
        arbiter_confidence:
          anyOf:
          - type: number
          - type: 'null'
          title: Arbiter Confidence
          description: How certain the arbiter is of its own verdict (0-1).
        arbiter_cost_usd:
          anyOf:
          - type: number
          - type: 'null'
          title: Arbiter Cost Usd
          description: What the inference actually cost. 0 on tier=cheap by design; 0 on standard/max means no model ran and the verdict is not a real evaluation.
        arbiter_reason:
          anyOf:
          - type: string
          - type: 'null'
          title: Arbiter Reason
          description: The arbiter's stated reason for the verdict, in plain language.
        arbiter_latency_ms:
          anyOf:
          - type: integer
          - type: 'null'
          title: Arbiter Latency Ms
          description: Wall-clock time the arbiter took, in milliseconds.
        evidence_content_hash:
          anyOf:
          - additionalProperties: true
            type: object
          - type: 'null'
          title: Evidence Content Hash
          description: SHA-256 fetch+hash record for every referenced evidence deliverable ({algorithm, entries, deliverables, hashed, root, computed_at}). Null until the verification chokepoint has hashed the deliverables.
        durable_evidence:
          anyOf:
          - additionalProperties: true
            type: object
          - type: 'null'
          title: Durable Evidence
          description: 'DX402 anchor receipt: a copy of this delivery, encrypted to the BUYER''s own key and anchored at the facilitator, recoverable months later with GET /dx402/evidence/{paymentId}. Carries {paymentId, pointer, backend, contentHash, cipher, keyAlg, mode, retention, receipt}; contentHash is over the PLAINTEXT, so a seller who anchored something other than what it served is detectable. Null means no evidence was anchored (buyer key not recoverable, non-EVM network, task opted out, or the anchor failed) - never an error.'
        verification_seal:
          anyOf:
          - additionalProperties: true
            type: object
          - type: 'null'
          title: Verification Seal
          description: 'The evidence analysis this task''s publisher pre-paid at publish with `premium_verification: true`, and the only place they read it: {report, seal, seal_signature, signer, paid_by}. `report` carries {verdict, score, summary, artifact_hashes, model, analyzed_at}; `seal` is the canonical payload that was signed. Check it WITHOUT trusting this API: ecrecover over the seal JSON must return `signer`, and `signer` must equal IdentityRegistry.ownerOf(2106) on-chain. `paid_by` says who bought it — ''publisher'' for the pre-paid add-on and the post-hoc purchase, ''executor'' when the worker bought their own. Null means no analysis was purchased for this submission.'
      type: object
      required:
      - id
      - task_id
      - executor_id
      - status
      - submitted_at
      title: SubmissionResponse
      description: Response model for submission data.
    RejectionRequest:
      properties:
        notes:
          type: string
          maxLength: 1000
          minLength: 10
          title: Notes
          description: Required reason for rejection
        severity:
          type: string
          pattern: ^(minor|major)$
          title: Severity
          description: 'Rejection severity: ''minor'' (no on-chain effect) or ''major'' (records negative reputation)'
          default: minor
        reputation_score:
          anyOf:
          - type: integer
            maximum: 50.0
            minimum: 0.0
          - type: 'null'
          title: Reputation Score
          description: Reputation score for major rejections (0-50). Defaults to 30 if omitted.
      additionalProperties: false
      type: object
      required:
      - notes
      title: RejectionRequest
      description: Request model for rejecting a submission.
    SuccessResponse:
      properties:
        success:
          type: boolean
          title: Success
          description: Whether the operation succeeded
          default: true
        message:
          type: string
          title: Message
          description: Human-readable result message
        data:
          anyOf:
          - additionalProperties: true
            type: object
          - type: 'null'
          title: Data
          description: Additional response data
      type: object
      required:
      - message
      title: SuccessResponse
      description: Generic success response.
  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