> ## 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.

# Close an intent you reconciled by hand

> Closes an Execution Intent in state `PREPARED` or `ERRORED` after a verified human reconciled it at the connector (G-54).



## OpenAPI

````yaml openapi.bundled.yaml POST /execution-intents/{businessTransactionId}/resolve
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/{businessTransactionId}/resolve:
    post:
      tags:
        - Execution Intents
      summary: Close an intent you reconciled by hand
      description: >
        Closes an Execution Intent in state `PREPARED` or `ERRORED` after a
        verified human reconciled it at the connector (G-54). Those are the
        intents whose outcome only an operator can establish, because no
        execution result was saved. The body records what you found
        (`NOT_EXECUTED` or `EXECUTED`) and a required note. The intent moves to
        `RESOLVED` and leaves `GET /execution-intents/unfinalized`. It never
        calls a connector. It is idempotent: resolving an intent that is already
        `RESOLVED` changes nothing and returns `ALREADY_RESOLVED` with the
        original resolution, note and author. It refuses a `RELEASED` intent,
        because its execution result is saved and `finalize` is the right
        operation, and it refuses a `FINALIZED` intent, or any intent whose
        transaction already has a signed Trust Record. **The resolution is an
        attributed, timestamped statement by an operator, stored in the intent's
        unsigned status. It is not tamper evident and it is not a Trust
        Record.** Requires a credential provisioned as a verified human
        (`credentialHolderType: USER`), otherwise `403` with code
        `NON_HUMAN_CALLER_DENIED`.
      operationId: resolveExecutionIntent
      parameters:
        - name: businessTransactionId
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/execution-intent-resolve-request.schema'
      responses:
        '200':
          description: >-
            The intent is closed. `outcome` says whether this call closed it
            (`RESOLVED`) or it was already closed (`ALREADY_RESOLVED`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/execution-intent-resolve-response.schema'
        '400':
          description: >-
            The body is invalid. `resolution` must be `NOT_EXECUTED` or
            `EXECUTED`, and `note` is required, at most 2000 characters. Nothing
            was changed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/error.schema'
              examples:
                noteRequired:
                  summary: Message text from the source
                  value:
                    error: >-
                      The resolution is invalid: note is required. Record what
                      you found at the connector.
                    code: EXECUTION_INTENT_RESOLUTION_INVALID
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: The credential is not provisioned as a verified human.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/error.schema'
              examples:
                nonHumanCaller:
                  summary: Real captured response
                  value:
                    error: >-
                      This action requires a caller credential provisioned as a
                      verified human (credentialHolderType: USER).
                    code: NON_HUMAN_CALLER_DENIED
        '404':
          description: No Execution Intent exists for this businessTransactionId.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/error.schema'
              examples:
                notFound:
                  summary: Message text from the source
                  value:
                    error: >-
                      No Execution Intent exists for business transaction
                      'unknown-transaction'. Transactions created before
                      Execution Intents were introduced have none.
                    code: EXECUTION_INTENT_NOT_FOUND
        '409':
          description: >-
            The intent cannot be resolved by hand. It is `RELEASED` (use
            finalize), `FINALIZED`, or a signed Trust Record already exists for
            the transaction. Nothing was changed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/error.schema'
              examples:
                released:
                  summary: Message text from the source
                  value:
                    error: >-
                      The Execution Intent for business transaction
                      'b1237ce3-305a-4004-8179-749352fc1ade' is in state
                      RELEASED and cannot be resolved by hand. Its execution
                      result was saved, so rebuild the signed Trust Record with
                      finalize instead. Nothing was changed.
                    code: EXECUTION_INTENT_NOT_RESOLVABLE
        '501':
          description: Execution Intents are not enabled on this deployment.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/error.schema'
              examples:
                notEnabled:
                  summary: Message text from the source
                  value:
                    error: Execution Intents are not enabled on this deployment.
                    code: EXECUTION_INTENTS_NOT_ENABLED
components:
  schemas:
    execution-intent-resolve-request.schema:
      title: Resolve Execution Intent Request
      description: >-
        Request body for POST
        /execution-intents/{businessTransactionId}/resolve. Both fields are
        required. The note is required on purpose, because it is the only record
        of what the operator found at the connector.
      type: object
      additionalProperties: false
      required:
        - resolution
        - note
      properties:
        resolution:
          type: string
          enum:
            - NOT_EXECUTED
            - EXECUTED
          description: >-
            What you established at the connector. NOT_EXECUTED: the action did
            not run. EXECUTED: it did run.
        note:
          type: string
          minLength: 1
          maxLength: 2000
          description: >-
            What you checked and found, for example the connector and the
            reference you looked at. Surrounding space is trimmed.
      examples:
        - resolution: NOT_EXECUTED
          note: Checked the Paytm dashboard for this order. No refund exists.
    execution-intent-resolve-response.schema:
      title: Resolve Execution Intent Response
      description: >-
        Response returned by POST
        /execution-intents/{businessTransactionId}/resolve. RESOLVED means this
        call closed the intent. ALREADY_RESOLVED means it was already closed and
        nothing was changed: the original resolution, note and author are
        returned, never the new request's.
      type: object
      additionalProperties: false
      required:
        - outcome
        - businessTransactionId
        - intent
        - status
      properties:
        outcome:
          type: string
          enum:
            - RESOLVED
            - ALREADY_RESOLVED
        businessTransactionId:
          type: string
        intent:
          $ref: '#/components/schemas/execution-intent.schema'
        status:
          $ref: '#/components/schemas/execution-intent-status.schema'
    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
    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
    execution-intent-status.schema:
      title: Execution Intent Status
      description: >-
        Operational status kept next to a signed Execution Intent. It is NOT
        part of what is signed, so it changes as the request progresses.
        PREPARED: the intent is signed and stored, and the action may or may not
        have been released. An intent that stays PREPARED needs reconciliation
        with the connector. RELEASED: the release stage returned and the
        execution context was saved, so the Trust Record can be rebuilt.
        FINALIZED: a signed Execution Trust Record exists for this transaction.
        ERRORED: the release stage raised an error. The action may still have
        been executed, so the outcome is unknown and must be reconciled.
        RESOLVED: a verified human reconciled a PREPARED or ERRORED intent at
        the connector and closed it with POST
        /execution-intents/{businessTransactionId}/resolve, recording what they
        found and a note. The resolution is an attributed operator statement
        stored in this unsigned status. It is NOT tamper evident and it is not a
        Trust Record.
      type: object
      additionalProperties: true
      required:
        - state
      properties:
        state:
          type: string
          enum:
            - PREPARED
            - RELEASED
            - FINALIZED
            - ERRORED
            - RESOLVED
        releasedAt:
          type: string
          format: date-time
          description: >-
            When the release stage returned and the execution context was saved.
            Absent from PREPARED and from an ERRORED intent.
        finalizedAt:
          type: string
          format: date-time
          description: >-
            When the intent was marked FINALIZED. Present only when state is
            FINALIZED.
        finalizationMode:
          type: string
          enum:
            - INLINE
            - REPAIRED
          description: >-
            INLINE: the Trust Record was produced in the original request.
            REPAIRED: it was rebuilt afterwards by POST
            /execution-intents/{businessTransactionId}/finalize. Present only
            when state is FINALIZED.
        trustRecordId:
          type: string
          description: >-
            The Execution Trust Record for this transaction. Present only when
            state is FINALIZED.
        failureReason:
          type: string
          description: >-
            The error message the release stage raised. Present only when state
            is ERRORED.
        resolution:
          type: string
          enum:
            - NOT_EXECUTED
            - EXECUTED
          description: >-
            What the operator found at the connector. Present only when state is
            RESOLVED.
        resolutionNote:
          type: string
          description: >-
            The operator's note. Required when resolving. Present only when
            state is RESOLVED.
        resolvedBy:
          type: string
          description: >-
            The authenticated caller who resolved it. Absent when caller
            authentication is disabled.
        resolvedAt:
          type: string
          format: date-time
          description: When it was resolved. Present only when state is RESOLVED.
      examples:
        - state: FINALIZED
          releasedAt: '2026-09-21T05:40:32.743Z'
          finalizedAt: '2026-09-21T05:40:32.855Z'
          finalizationMode: INLINE
          trustRecordId: a3c8d068-af6a-46c7-9976-e43612d5ab9c
  responses:
    Unauthorized:
      description: >-
        Missing or invalid caller credential (StaticKeyAuthenticator returned no
        identity). Real captured response,
        packages/api/src/middleware/caller-auth.ts.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/error.schema'
          examples:
            authRequired:
              summary: Real captured response, missing or invalid Authorization header
              value:
                error: authentication required
  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.

````