> ## Documentation Index
> Fetch the complete documentation index at: https://docs.parmanasystems.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Verify an Execution Intent's signature

> Verifies an Execution Intent's hash and signature (ADR-0012).



## OpenAPI

````yaml openapi.bundled.yaml POST /execution-intents/verify
openapi: 3.1.0
info:
  title: Parmana API
  version: 1.0.0
  description: >
    Parmana is an Execution Trust Infrastructure that ensures there is no gap
    between what humans decide and what AI systems do. The API enables creation,
    execution, verification, replay, and auditing of Business Transactions
    through cryptographically verifiable Execution Trust Records.


    **Every route requires a caller bearer key**, except the liveness/readiness
    probes and documentation/verification routes that must be reachable with no
    credential: GET /health, GET /ready, GET /openapi.yaml, GET /documentation,
    GET /reference, POST /refusal/verify, POST /execution-intents/verify, POST
    /audit/verify, GET /keys/{keyId}, and GET /.well-known/jwks.json. Send
    `Authorization: Bearer <key>` on every other request. Keys are issued by
    `scripts/generate-api-key.ts` and configured server-side via
    `PARMANA_API_KEYS`; only a hash of each key is ever held by the server,
    verified in constant time. A missing or invalid credential returns 401
    before a Business Transaction is even constructed, independent of Policy
    evaluation and gateway attestation, see
    `packages/api/src/middleware/caller-auth.ts` and
    [Authentication](/api-reference/authentication). Local development may set
    `PARMANA_AUTH_DISABLED=true` to skip this middleware entirely; that flag
    must never be set in a real deployment.
  contact:
    name: Parmana Systems
    email: founder@parmanasystems.com
  license:
    name: Proprietary, source-available for evaluation only, see LICENSE
    url: https://github.com/pavancharak/AgentLabsBuildathon/blob/main/LICENSE
servers:
  - url: https://parmana-api-real.vercel.app
    description: >-
      Production (real, deployed instance -- the docs site playground uses this
      by default)
  - url: http://localhost:3000
    description: Local (packages/api, PORT env var, default 3000)
security:
  - bearerAuth: []
tags:
  - name: Execution
    description: >-
      Executes a Business Transaction through the complete Execution Trust
      pipeline
  - name: Transactions
    description: Business Transaction creation and retrieval
  - name: Verification
    description: Deterministic verification of an Execution Trust Record
  - name: Receipts
    description: Cryptographically signed Execution Trust Receipts
  - name: Trust Records
    description: Execution Trust Record retrieval
  - name: Replay
    description: Deterministic replay of a recorded Execution Trust Record
  - name: Policies
    description: Policy existence/readability check
  - name: Policy Governance
    description: Maker-checker proposal, listing, approval, and rejection of policy changes
  - name: Refusal Records
    description: >-
      Durable, signed evidence that a policy decision rejected a transaction
      (RFC-0021)
  - name: Execution Intents
    description: >-
      A signed statement, stored before an action is released, of exactly what
      is about to be released, plus the operator tools to find and repair a
      released action that has no signed Trust Record (ADR-0012)
  - name: Audit
    description: >-
      Signed caller-authentication audit events, independently
      third-party-verifiable
  - name: System
    description: Operational endpoints
paths:
  /execution-intents/verify:
    post:
      tags:
        - Execution Intents
      summary: Verify an Execution Intent's signature
      description: >
        Verifies an Execution Intent's hash and signature (ADR-0012).
        Deliberately mounted before this app's caller-auth middleware, see
        packages/api/src/app.ts: no caller authentication or API key is
        required, by design, the same as POST /refusal/verify. It takes the
        intent itself, reads no storage, and needs nothing but the artifact and
        Parmana's public key. A `valid: true` result proves the intent was
        signed by the holder of the key and has not been altered. It does NOT
        prove the action was released, or what its result was, because an intent
        is written BEFORE release. To check the outcome, look for the signed
        Execution Trust Record for the same businessTransactionId. For a check
        that needs no call to this API at all, use
        scripts/verify-execution-intent.ts with the public key from GET
        /keys/{keyId}.
      operationId: verifyExecutionIntent
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/execution-intent.schema'
      responses:
        '200':
          description: >-
            Verification completed. A 200 does not by itself mean the signature
            verified, see the valid field.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/verify-result-response.schema'
              examples:
                valid:
                  summary: Real captured response
                  value:
                    valid: true
                altered:
                  summary: >-
                    The same intent with its target changed after signing (real
                    captured response)
                  value:
                    valid: false
        '400':
          description: Request body is not a structurally plausible Execution Intent.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/error.schema'
              examples:
                malformed:
                  summary: Message text from the source
                  value:
                    error: >-
                      Request body must be an Execution Intent (intentId,
                      businessTransactionId, authorizationId, intentHash,
                      signature required).
      security: []
components:
  schemas:
    execution-intent.schema:
      title: Execution Intent
      description: >-
        A signed statement, made and stored BEFORE an action is released to a
        connector, of exactly what is about to be released (ADR-0012). It exists
        so that an action that was released always has signed evidence behind
        it, even when the Execution Trust Record cannot be produced afterwards.
        It contains only facts that exist before release: never the execution
        result, and never the raw intent parameters (the businessTransactionHash
        binds the intent to them). It is a separate record from the Execution
        Trust Record, which keeps its own format. An intent proves what was
        about to be released. It does NOT prove the action was released or what
        its result was. At most one Execution Intent exists per
        businessTransactionId.
      type: object
      additionalProperties: true
      required:
        - intentId
        - businessTransactionId
        - decisionId
        - authorizationId
        - policyName
        - policyVersion
        - businessTransactionHash
        - action
        - target
        - createdAt
        - intentHash
        - signature
      properties:
        intentId:
          type: string
          description: Unique Execution Intent identifier.
        businessTransactionId:
          type: string
          description: The Business Transaction this intent belongs to.
        decisionId:
          type: string
          description: The Decision that approved the action.
        authorizationId:
          type: string
          description: >-
            The signed execution authorization this intent refers to. Matches
            authorization.payload.authorizationId in the Execution Trust Record.
        policyName:
          type: string
        policyVersion:
          type: string
        policyContentHash:
          type: string
          description: >-
            Hash of the exact policy content in force, copied from the signed
            authorization. Absent when the authorization carries none.
        signalsHash:
          type: string
          description: >-
            Hash of the signals that were evaluated, copied from the signed
            authorization. Absent when the authorization carries none.
        businessTransactionHash:
          type: string
          description: >-
            Hash of the executable content (action, target and parameters),
            copied from the signed authorization. It binds the intent to the
            exact parameters that were authorized without repeating them here.
        action:
          type: string
          description: The capability about to be released, for example paytm:refund.
        target:
          type: string
          description: >-
            The target of the action, for example the order being refunded.
            Together with action and businessTransactionId it is what an
            operator searches for at the connector.
        submittedBy:
          type: string
          description: >-
            Authenticated caller who submitted the request. Absent when caller
            authentication is disabled.
        grantedCapability:
          type: string
          description: The capability the caller was granted, when one was recorded.
        createdAt:
          type: string
          format: date-time
          description: >-
            UTC timestamp when the intent was created, before the action was
            released.
        intentHash:
          type: string
          description: >-
            Canonical hash of the intent, same convention as
            ExecutionTrustRecord.trustRecordHash.
        signature:
          type: object
          description: >-
            Signature over the canonical Execution Intent, made with the
            deployment's signing key (local or AWS KMS), the same root of trust
            as the Execution Trust Record.
          additionalProperties: true
          required:
            - algorithm
            - keyId
            - value
            - signedAt
          properties:
            algorithm:
              type: string
              examples:
                - ed25519
            keyId:
              type: string
              description: >-
                Identifier of the signing key. Fetch its public half from GET
                /keys/{keyId}.
            value:
              type: string
              description: Base64 encoded signature value.
            signedAt:
              type: string
              format: date-time
      examples:
        - intentId: b41fe9b9-5730-4d34-aab0-4ab63ae69d3b
          businessTransactionId: 4c2eb3b2-3382-4bc2-bf22-2a072e6cf428
          decisionId: 20b4e030-09cd-4447-86fc-b73279d23121
          authorizationId: 5977535b-d887-423d-b422-01ece1fc7bf1
          policyName: customer-refund
          policyVersion: 1.0.0
          policyContentHash: 6a2e92fbde0f4c5dc56b4e202bf45ce24c99e565cf3ddaacaa21a11c71b7e1ea
          signalsHash: e22a7b9fd6e0a39e28521f9ffb726d6a57499236055fa6ff2caabd2268f4a395
          businessTransactionHash: 9df286daf38c6eba272f47153e0fb3efef5ee61d778f6baecd5a53861763763a
          action: paytm:refund
          target: DRY-ORDER-1789969223742
          submittedBy: sandbox-agent
          grantedCapability: paytm:refund
          createdAt: '2026-09-21T05:40:28.434Z'
          intentHash: 13922de380518d582c6bb3e88b1d88908e71565f191119f4cadc7de4e30cf5ed
          signature:
            keyId: default
            value: >-
              UhXnkSnm5A3QU4CVrKGbP3FcTWkShnitn86psJprJpqgEBnsXWzDcZ+ktSO0FJek1X+n9DvO3SjR+WvSofS1CA==
            signedAt: '2026-09-21T05:40:28.555Z'
            algorithm: ed25519
    verify-result-response.schema:
      title: Verify Result Response
      description: >-
        Response shared by POST /refusal/verify and POST /audit/verify: a bare
        signature-validity result, no wrapper, no partial-failure detail. Both
        routes verify a signature over bytes with no database lookup, so there
        is nothing more specific to report than valid or not.
      type: object
      additionalProperties: false
      required:
        - valid
      properties:
        valid:
          type: boolean
          description: >-
            Whether the signature verifies against Parmana's public key for the
            stated algorithm and key ID.
      examples:
        - valid: true
        - valid: false
    error.schema:
      title: Error Response
      description: >-
        Shared error envelope produced by
        packages/api/src/middleware/error-handler.ts and by every route's inline
        validation checks. error is always a plain human-readable string (never
        a nested object). code is present only when the failure was a
        RuntimeError subclass reaching the centralized error handler
        (VerificationFailedError, ReceiptGenerationError, or an uncategorized
        RuntimeError); it is absent from every inline route-level check
        (businessTransactionId format/required checks) and from
        BusinessTransactionValidationError, PolicyValidationError,
        SignalValidationError, PolicyNotFoundError,
        DuplicateBusinessTransactionError, and the generic 500 fallback. POST
        /policies/validate does NOT use this envelope at all. See its own
        response schema. For the triggering condition and recommended caller
        action behind any specific error/code/status combination, see the Error
        catalog at /api-reference/error-catalog.
      type: object
      additionalProperties: false
      required:
        - error
      properties:
        error:
          type: string
          description: Human-readable error message.
        code:
          type: string
          description: >-
            Stable machine-readable error code. Only present for errors that
            reach the handler as a RuntimeError.
          examples:
            - RUNTIME_ERROR
            - VERIFICATION_FAILED
            - RECEIPT_GENERATION_FAILED
            - POLICY_DENIED
            - CAPABILITY_NOT_ALLOWED
            - RATE_LIMITED
            - AUDIT_UNAVAILABLE
            - SIGNING_UNAVAILABLE
            - CONNECTOR_NOT_REGISTERED
            - EXECUTION_RECORD_INCOMPLETE
            - EXECUTION_INTENT_UNAVAILABLE
            - EXECUTION_INTENT_RESULT_NOT_RECORDED
            - EXECUTION_INTENT_NOT_FOUND
            - EXECUTION_INTENTS_NOT_ENABLED
            - EXECUTION_INTENT_NOT_RESOLVABLE
            - EXECUTION_INTENT_RESOLUTION_INVALID
            - NON_HUMAN_CALLER_DENIED
      examples:
        - error: businessTransactionId must be a valid UUID.
        - error: >-
            Business Transaction 'eed2a972-1bf5-4166-8472-761f76fbf1b2' already
            exists.
        - error: >-
            Execution rejected: Vendor payment rejected because the assessed
            payment risk exceeds the maximum permitted threshold.
          code: RUNTIME_ERROR
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >
        Caller API key issued by scripts/generate-api-key.ts. Sent as
        Authorization: Bearer <key>. Verified against a stored SHA-256 hash in
        constant time by packages/api/src/auth/StaticKeyAuthenticator.ts.
        Required on every route not listed as exempt in this document's
        top-level description. See /api-reference/authentication.

````