openapi: 3.2.0 info: title: Proof Verifiable Credentials API Specification OID4VP API version: v1 servers: - url: https://api.proof.com description: Public API URL tags: - name: OID4VP paths: /verifiable-credentials/v1/presentation/authorize: get: summary: Authorize Verifiable Credential Presentation tags: - OID4VP operationId: authorizeVerifiableCredentialPresentation description: 'Initiates an OID4VP Verifiable Credential Presentation request for the End-User identified by their Proof session, or by `login_hint` when they are not signed in. Returns a 302 redirect to the Proof-hosted flow where the End-User authorizes the presentation. Once complete, Proof returns the Verifiable Credential Presentation according to `response_mode`: for `fragment`, the `vp_token` is appended as a URL fragment on a redirect back to `redirect_uri`; for `direct_post`, the `vp_token` is POSTed to `response_uri`.' parameters: - name: client_id in: query required: true description: Your Proof OAuth Application Client ID. schema: type: string - name: response_type in: query required: true schema: type: string enum: - vp_token description: The method used to return the Verifiable Credential Presentation. Only `vp_token` is supported. - name: response_mode in: query required: true schema: type: string enum: - fragment - direct_post description: How the Verifiable Credential Presentation will be returned to the Verifier. Use `fragment` to have the `vp_token` returned as a URL fragment on a redirect to `redirect_uri`, or `direct_post` to have Proof POST the `vp_token` to `response_uri`. - name: redirect_uri in: query required: false description: Required when `response_mode` is `fragment`; not permitted otherwise. The redirect URI at which the Verifiable Credential Presentation will be returned as a URL fragment. Must match a redirect URI registered on your OAuth Application. schema: type: string - name: response_uri in: query required: false description: Required when `response_mode` is `direct_post`; not permitted otherwise. The URI to which Proof will POST the Verifiable Credential Presentation. Must match a redirect URI registered on your OAuth Application. schema: type: string - name: scope in: query required: true schema: type: string enum: - urn:proof:params:scope:verifiable-credentials:basic description: Space-separated list of scopes that translate to DCQL queries. - name: login_hint in: query required: false description: 'The email address associated with the End-User you''re requesting Verifiable Credential presentation from. Optional: an End-User signed in to Proof takes precedence over `login_hint`. When omitted, the End-User is sent through login first if they are not already signed in.' schema: type: string - name: nonce in: query required: true description: Opaque client-generated value bound to the presentation response to prevent replay. schema: type: string - name: state in: query required: false description: Opaque value echoed back on the redirect to maintain state between the request and the callback. schema: type: string - name: transaction_data in: query required: false example: eyJ0eXBlIjoidXJuOnByb29mOnBhcmFtczp2Yzp0cmFuc2FjdGlvbi1kYXRhOnNlc3Npb24tZGF0YSIsImNyZWRlbnRpYWxfaWRzIjpbInByb29mX2lkX2RlZmF1bHQiXSwicGF5bG9hZCI6eyJpcF9hZGRyZXNzIjoiMjAzLjAuMTEzLjAiLCJkZXZpY2VfaWQiOiJkZXZpY2UtMTk4OSJ9fQ description: "Space-separated base64url-encoded JSON objects. Each object carries transaction details the Verifier is asking the End-User to authorize, with the shape: \n\n- `type` (string, required): one of `urn:proof:params:vc:transaction-data:session-data`, `urn:proof:params:vc:transaction-data:payment-itemized:v1`, `urn:proof:params:vc:transaction-data:wire-instructions:v1`, or `urn:proof:params:vc:transaction-data:payment-mandate:v1`.\n- `credential_ids` (array of strings, required): must be a single-element array matching the credential ID targeted by `scope` (currently `proof_id_default`).\n- `payload` (object, required): type-specific fields authorized by the End-User.\n\nExample (decoded): `{\"type\":\"urn:proof:params:vc:transaction-data:session-data\",\"credential_ids\":[\"proof_id_default\"],\"payload\":{\"ip_address\":\"203.0.113.0\",\"device_id\":\"device-1989\"}}`." schema: type: string responses: '302': description: successful headers: Location: schema: type: string description: URL of the Proof-hosted flow where the End-User authorizes the Verifiable Credential Presentation. '400': description: Bad Request content: application/json: example: errors: request: - unauthorized_client schema: $ref: '#/components/schemas/errors_object' /verifiable-credentials/v1/x401-handoff: post: summary: Hand off an x401 Verifiable Credential Presentation request tags: - OID4VP operationId: createPresentationX401Handoff description: 'Accepts an x401 payload (https://x401.proof.com/spec/latest/#x401-payload) that wraps a Digital Credentials API request (https://www.w3.org/TR/digital-credentials/#DC-API) using the `openid4vp-v1-signed` protocol, and processes it as an OID4VP presentation request for the End-User identified by the `login_hint` claim of the signed request object. When the request carries a Proof access token issued to an End-User in the `Authorization: Bearer` header, that End-User is used instead of `login_hint`, and an invalid token is rejected with `invalid_token`. The real OID4VP request is carried inside the signed request object at `credential_requirements.digital.requests[0].data.request`: a compact JWS with `typ` header `oauth-authz-req+jwt`, signed with ES256 by a key whose JWK is registered on your OAuth Application. Your `client_id` is conveyed by the request object''s `iss`/`client_id` claims. Its `response_mode` must be `dc_api`. It must carry an `exp` claim at most one hour ahead and a unique `jti` claim; a request object is accepted once. On success Proof returns a `request_uri` suitable for presenting to the End-User via their AI agent. Supply a top-level `return_uri` to use the x401 intermediary return channel (https://x401.proof.com/spec/latest/#return-channel); its origin must appear in the request object''s `expected_origins`. AI agents that cannot receive the presentation themselves omit `return_uri` and send an access token with the `agentic` scope. This requires the request object''s `expected_origins` to be the agents trust list. Proof then also returns a `result_polling_uri` the agent polls with the same access token.' parameters: - name: Authorization in: header required: false description: Optional `Bearer` access token issued by Proof to the End-User, with the `mcp.read` or `agentic` scope. When present, the transaction is created for that End-User instead of `login_hint`. Required, with the `agentic` scope, to receive a `result_polling_uri`. schema: type: string responses: '201': description: Created content: application/json: example: request_uri: https://link.local.dev-notarize.com/s/dfjULr2l6TklX0fn47iYkQ schema: $ref: '#/components/schemas/x401_handoff_response' '400': description: Bad Request content: application/json: example: errors: request: - payload is invalid schema: $ref: '#/components/schemas/errors_object' '401': description: Unauthorized content: application/json: example: error: invalid_token error_description: invalid access token schema: $ref: '#/components/schemas/oauth_error' requestBody: content: application/json: schema: $ref: '#/components/schemas/x401_payload' required: true /verifiable-credentials/v1/x401-result/{id}: get: summary: Poll an x401 Verifiable Credential Presentation result tags: - OID4VP operationId: getX401Result description: Returns the Verifiable Credential Presentation of an x401 handoff created without `return_uri`, once the End-User completes the flow. The End-User may take several minutes (identity verification). Poll no faster than the `Retry-After` header of a `202` response. A pending result expires after one hour, a completed result five minutes after completion. Only the End-User of the access token that created the handoff can read the result; any other caller receives `404`. parameters: - name: Authorization in: header required: true description: '`Bearer` access token with the `agentic` scope, issued to the End-User who created the handoff.' x-example: Bearer jgH4e1KzCYdJAxZqbdJj5MCik0g1swUG4MKfdQPmfB0 schema: type: string - name: id in: path required: true description: The transaction identifier ending the `result_polling_uri` returned by the handoff. x-example: ot123 schema: type: string responses: '200': description: Completed content: application/json: example: status: completed credential_result: protocol: openid4vp-v1-signed data: vp_token: eyJwcm9vZl9pZF9kZWZhdWx0IjpbIi4uLiJdfQ schema: $ref: '#/components/schemas/x401_result_response' '202': description: Pending headers: Retry-After: schema: type: integer description: Seconds to wait before polling again. content: application/json: example: status: pending schema: $ref: '#/components/schemas/x401_result_response' '401': description: Unauthorized content: application/json: example: error: invalid_token error_description: invalid access token schema: $ref: '#/components/schemas/oauth_error' '404': description: Not Found content: application/json: example: error: not_found error_description: unknown or expired x401 result schema: $ref: '#/components/schemas/oauth_error' /verifiable-credentials/v1/x401-signatures: post: summary: Fetch the detached signatures of an x401 Verifiable Credential Presentation tags: - OID4VP operationId: getX401Signatures description: 'Presentations delivered through x401 to an organization billed by invoice, with no card or bank account on file, omit the signature segment of both the Issuer-signed JWT and the Key Binding JWT. The Key Binding JWT header carries a critical `proof.com#sig-1` parameter whose value is the `id` to send here. Authenticate with a `private_key_jwt` client assertion from the OAuth Application that requested the presentation, with `aud` set to this endpoint URL. When the transaction is not yet paid, the first call answers `402` with x402 payment requirements (https://www.x402.org) for the transaction price; repeat the request with the `PAYMENT-SIGNATURE` header to settle and receive the signatures. A `409` means the transaction is still being finalized: retry after the `Retry-After` delay. Records expire one hour after the presentation.' parameters: [] responses: '200': description: OK content: application/json: example: issuer_signature: isig kb_signature: ksig schema: $ref: '#/components/schemas/x401_signature_response' '401': description: Unauthorized content: application/json: example: error: invalid_client error_description: invalid client assertion schema: $ref: '#/components/schemas/oauth_error' '402': description: Payment Required headers: PAYMENT-REQUIRED: schema: type: string description: Base64 x402 payment requirements; the body carries the same JSON. content: application/json: example: x402Version: 2 error: Payment required to access this resource resource: url: http://api.local.dev-notarize.com/verifiable-credentials/v1/x401-signatures description: Payment required for /verifiable-credentials/v1/x401-signatures mimeType: application/json accepts: - scheme: exact network: eip155:84532 amount: '5000000' asset: '0x036CbD53842c5426634e7929541eC2318f3dCF7e' payTo: '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' maxTimeoutSeconds: 600 extra: name: USDC version: '2' extensions: {} '404': description: Not Found content: application/json: example: error: not_found error_description: unknown or expired signature record schema: $ref: '#/components/schemas/oauth_error' '409': description: Conflict headers: Retry-After: schema: type: integer description: Seconds to wait before retrying. content: application/json: example: error: charges_pending error_description: the transaction is still being finalized, retry shortly schema: $ref: '#/components/schemas/oauth_error' requestBody: content: application/json: schema: type: object required: - id - client_assertion_type - client_assertion properties: id: type: string description: The value of the `proof.com#sig-1` header parameter of the Key Binding JWT. client_assertion_type: type: string enum: - urn:ietf:params:oauth:client-assertion-type:jwt-bearer client_assertion: type: string description: A `private_key_jwt` assertion signed by a key registered on your OAuth Application, with `aud` set to this endpoint URL. example: client_assertion_type: urn:ietf:params:oauth:client-assertion-type:jwt-bearer client_assertion: eyJraWQiOiJRTlBVLXFhZVpJMG5OMnM2REtLdWRqc3ZSTG5ScHB0XzFsWVpicmFrUWFJIiwiYWxnIjoiRVMyNTYifQ.eyJpc3MiOiJodHRwczovL2NsaWVudC5leGFtcGxlLmNvbS9tZXRhZGF0YS5qc29uIiwic3ViIjoiaHR0cHM6Ly9jbGllbnQuZXhhbXBsZS5jb20vbWV0YWRhdGEuanNvbiIsImF1ZCI6Imh0dHBzOi8vYXBpLmxvY2FsLmRldi1ub3Rhcml6ZS5jb20vdmVyaWZpYWJsZS1jcmVkZW50aWFscy92MS94NDAxLXNpZ25hdHVyZXMiLCJleHAiOjE3OTE5MDgwNDIsImp0aSI6Ijg1NDQyMTEwLTE2ZGUtNGU2Yy04OTE0LTA2NmI0NDE1ZTVkYiJ9.Xm8lR3z67eM4oVxAxpdFUvXhAGVn_lk2uA7BnVMcxlPphEqDdiRj2mOvXLWPus-G4N5V5yOBAGqZYn6jWBCpKA id: 496Rozlk1s_Hw0Loor9sEw required: true components: schemas: errors_object: type: object properties: errors: type: object properties: request: type: array items: type: string x401_result_response: type: object required: - status properties: status: type: string enum: - pending - completed description: '`pending` while the End-User has not completed the flow, `completed` once the presentation is available.' credential_result: type: object description: Only present when `status` is `completed`. Use it as the `credential_result` member of an x401 Result Artifact (https://x401.proof.com/spec/latest/). required: - protocol - data properties: protocol: type: string enum: - openid4vp-v1-signed data: type: object required: - vp_token properties: vp_token: type: string description: The OID4VP `vp_token`, as Proof would have posted it to a `response_uri`. x401_handoff_response: type: object properties: request_uri: type: string description: A link to the Proof-hosted flow where the End-User authorizes the Verifiable Credential Presentation. result_polling_uri: type: string description: Only present when the request object's `expected_origins` is the agents trust list and `return_uri` is omitted. Poll this URI with the same `agentic` access token to retrieve the Verifiable Credential Presentation once the End-User completes the flow. oauth_error: type: object properties: error: type: string description: An [error code](https://datatracker.ietf.org/doc/html/rfc6749#section-5.2). error_description: type: string description: Human-readable detail about the error, for developers. x401_payload: type: object required: - credential_requirements properties: credential_requirements: type: object required: - digital properties: digital: type: object required: - requests properties: requests: type: array description: Must contain exactly one Digital Credentials API request. items: type: object required: - protocol - data properties: protocol: type: string enum: - openid4vp-v1-signed description: The DC API protocol. Only the signed variant `openid4vp-v1-signed` is supported. data: type: object required: - request properties: request: type: string description: 'The signed OID4VP request object (a JAR), as a compact JWS. It MUST have `typ` header `oauth-authz-req+jwt`, be signed with ES256 by a key whose JWK is registered on your OAuth Application, and carry the OID4VP request claims: `iss` (equal to `client_id`), `aud` (the Proof presentation issuer), `client_id`, `response_type` (`vp_token`), `response_mode` (`dc_api`), `scope`, `login_hint`, and `nonce`. For the intermediary flow, also include `expected_origins`. To let AI agents poll for the result instead, set `expected_origins` to exactly the agents trust list (`/.well-known/agents-trust-list` on this API host) and omit `response_uri`.' return_uri: type: string description: 'Optional. Enables the x401 intermediary return channel (https://x401.proof.com/spec/latest/#return-channel). When present, Proof POSTs the Verifiable Credential Presentation to this URI instead of the request object''s `response_uri`. Its origin must be listed in the request object''s `expected_origins`, and the request object must not itself specify a `response_uri`. Omit it when the request object''s `expected_origins` is the agents trust list: Proof then keeps the result for the calling agent to poll at `result_polling_uri`.' example: credential_requirements: digital: requests: - protocol: openid4vp-v1-signed data: request: eyJ0eXAiOiJvYXV0aC1hdXRoei1yZXErand0Iiwia2lkIjoicjktaWxvdnBTZ21IMm0tQ203QjgtMVpWNGlvUFFQZl9LbHAzT0ZtdUJEOCIsImFsZyI6IkVTMjU2In0.eyJpc3MiOiJjYWdua3JhZGoiLCJhdWQiOiJodHRwczovL2FwaS5sb2NhbC5kZXYtbm90YXJpemUuY29tL3ZlcmlmaWFibGUtY3JlZGVudGlhbHMvdjEvcHJlc2VudGF0aW9uIiwiY2xpZW50X2lkIjoiY2FnbmtyYWRqIiwicmVzcG9uc2VfdHlwZSI6InZwX3Rva2VuIiwicmVzcG9uc2VfbW9kZSI6ImRjX2FwaSIsInNjb3BlIjoidXJuOnByb29mOnBhcmFtczpzY29wZTp2ZXJpZmlhYmxlLWNyZWRlbnRpYWxzOmJhc2ljIiwibG9naW5faGludCI6ImphbmUuZG9lQHByb29mLmNvbSIsIm5vbmNlIjoiYThmODRmMGUtYjFkNi00MmVkLTg2YTctODc2OTliYjZmNjZkIiwiZXhwZWN0ZWRfb3JpZ2lucyI6WyJodHRwczovL2FnZW50LmV4YW1wbGUiXSwiZXhwIjoxNzkxOTA4MDQxLCJqdGkiOiJjY2YyNmRiMi0xMzZhLTRiMmQtOWU0My01MDQ1NWM5ZjA2ZTkifQ.OTsQRhNLkiEjImiDXD8h57PeUabXaBBtY1I-AHvBW3D6GMtMu6DLfLxW21BkBvTqjdsNx0KLQLXHl8zdEaP_Ug return_uri: https://agent.example/return x401_signature_response: type: object required: - issuer_signature - kb_signature properties: issuer_signature: type: string description: The base64url signature segment of the Issuer-signed JWT, to splice back into the first `~`-separated part of the SD-JWT. kb_signature: type: string description: The base64url signature segment of the Key Binding JWT, to splice back into the last `~`-separated part of the SD-JWT. x-provenance: method: searched source: https://dev.proof.com/reference harvested: '2026-10-14' tool: harvest-readme-openapi.py note: Assembled verbatim from the OpenAPI definition ReadMe embeds in each operation page of the provider's developer portal; paths and components merged by API title, nothing authored. assembled_from: - https://dev.proof.com/reference/authorizeverifiablecredentialpresentation.md - https://dev.proof.com/reference/createpresentationx401handoff.md - https://dev.proof.com/reference/getx401result.md - https://dev.proof.com/reference/getx401signatures.md merge: pages: 4 deduped: 3 conflicts_kept_first: 0