From 1a5e1bea55eb8cf69f1cad8c600d57da7829b7ab Mon Sep 17 00:00:00 2001 From: carsonp6 Date: Wed, 12 Aug 2026 15:53:39 -0700 Subject: [PATCH] docs(openapi): document the 202 processing-pending / retry-same-request contract (SP-3579) Several Embedded Wallet sync endpoints run their underlying wallet operation optimistically in line and can fall back to asynchronous processing. When that happens they return a non-terminal HTTP 202 with `{ "status": "PENDING" }`; the caller must re-send the identical request (same method, path, body, and headers) until it resolves to a terminal 200/201/204. Add a reusable `ProcessingPendingResponse` schema (status: PENDING) and reference it as a 202 on each affected endpoint: - POST /auth/credentials/{id}/verify (login: OTP / OAuth / passkey) - POST /auth/credentials/{id}/challenge (OTP init / passkey challenge) - POST /auth/sessions/{id}/refresh (session refresh) - POST /auth/credentials (add credential) - PATCH /customers/{customerId} (contact update: email / phone) - POST /auth/delegated-keys (delegated-key create) - DELETE /auth/delegated-keys/{id} (delegated-key revoke) - POST /internal-accounts/{id}/export (wallet export) Endpoints that already return a 202 signed-retry challenge now document an anyOf of that challenge or the pending marker, via named wrapper schemas (spectral forbids inline response schemas and oneOf without a discriminator). Document the retry contract in the endpoint descriptions and the Global Accounts authentication guide. Co-Authored-By: Claude Opus 4.8 --- mintlify/openapi.yaml | 101 +++++++++++++++--- .../global-accounts/authentication.mdx | 19 ++++ openapi.yaml | 101 +++++++++++++++--- ...edRequestChallengeOrProcessingPending.yaml | 14 +++ ...edRequestChallengeOrProcessingPending.yaml | 13 +++ .../common/ProcessingPendingResponse.yaml | 27 +++++ ...edRequestChallengeOrProcessingPending.yaml | 13 +++ openapi/paths/auth/auth_credentials.yaml | 26 +++-- .../auth/auth_credentials_{id}_challenge.yaml | 13 +++ .../auth/auth_credentials_{id}_verify.yaml | 30 ++++-- openapi/paths/auth/auth_delegated-keys.yaml | 17 ++- .../paths/auth/auth_delegated-keys_{id}.yaml | 11 ++ .../auth/auth_sessions_{id}_refresh.yaml | 22 +++- .../customers/customers_{customerId}.yaml | 27 +++-- .../internal_accounts_{id}_export.yaml | 19 +++- 15 files changed, 395 insertions(+), 58 deletions(-) create mode 100644 openapi/components/schemas/auth/AuthSignedRequestChallengeOrProcessingPending.yaml create mode 100644 openapi/components/schemas/auth/DelegatedKeySignedRequestChallengeOrProcessingPending.yaml create mode 100644 openapi/components/schemas/common/ProcessingPendingResponse.yaml create mode 100644 openapi/components/schemas/common/SignedRequestChallengeOrProcessingPending.yaml diff --git a/mintlify/openapi.yaml b/mintlify/openapi.yaml index d2332c99e..753d2c463 100644 --- a/mintlify/openapi.yaml +++ b/mintlify/openapi.yaml @@ -744,11 +744,14 @@ paths: schema: $ref: '#/components/schemas/CustomerOneOf' '202': - description: Challenge issued for an Embedded Wallet email or SMS auth phone update. The response contains `payloadToSign` plus a `requestId`. Build an API-key stamp over `payloadToSign` with the session API keypair from a verified authentication credential on one of the customer's tied Embedded Wallets, then retry the same request with `Grid-Wallet-Signature` and `Request-Id`. + description: |- + Non-terminal response for an Embedded Wallet email or SMS auth phone update, carrying one of two bodies distinguished by their fields. A signed-retry challenge (`payloadToSign` plus `requestId`) is returned on the initial call: build an API-key stamp over `payloadToSign` with the session API keypair from a verified authentication credential on one of the customer's tied Embedded Wallets, then retry the same request with `Grid-Wallet-Signature` and `Request-Id`. + + A still-processing body (`status: PENDING`) is returned when the operation ran optimistically in line but has fallen back to asynchronous processing — this can occur on the signed retry. Re-send the identical request, unchanged, on a short interval until it returns the terminal `200`. Do not add or alter a signature; the request is simply repeated as-is. content: application/json: schema: - $ref: '#/components/schemas/SignedRequestChallenge' + $ref: '#/components/schemas/SignedRequestChallengeOrProcessingPending' examples: embeddedWalletEmailUpdate: summary: Embedded Wallet customer email update challenge @@ -762,6 +765,10 @@ paths: payloadToSign: '{"organizationId":"org_2m9F...","parameters":{"userId":"user_2m9F...","userPhoneNumber":"+14155559876"},"timestampMs":"1775681700000","type":"ACTIVITY_TYPE_UPDATE_USER_PHONE_NUMBER"}' requestId: Request:019542f5-b3e7-1d02-0000-000000000011 expiresAt: '2026-04-08T15:35:00Z' + processingPending: + summary: Operation still processing (re-send the identical request) + value: + status: PENDING '400': description: Bad request content: @@ -5497,11 +5504,14 @@ paths: schema: $ref: '#/components/schemas/InternalAccountExportResponse' '202': - description: Challenge issued. The response contains `payloadToSign` (which binds the submitted `clientPublicKey`) plus a `requestId`. Build an API-key stamp over `payloadToSign` with the session API keypair and echo `requestId` on the retry. + description: |- + Non-terminal response carrying one of two bodies, distinguished by their fields. A signed-retry challenge (`payloadToSign`, which binds the submitted `clientPublicKey`, plus a `requestId`) is returned on the initial call: build an API-key stamp over `payloadToSign` with the session API keypair and echo `requestId` on the retry. + + A still-processing body (`status: PENDING`) is returned when the operation ran optimistically in line but has fallen back to asynchronous processing — this can occur on the signed retry. Re-send the identical request, unchanged (including the same `clientPublicKey`), on a short interval until it returns the terminal `200`. Do not add or alter a signature; the request is simply repeated as-is. content: application/json: schema: - $ref: '#/components/schemas/SignedRequestChallenge' + $ref: '#/components/schemas/SignedRequestChallengeOrProcessingPending' '400': description: Bad request content: @@ -5639,11 +5649,14 @@ paths: createdAt: '2026-04-08T15:30:01Z' updatedAt: '2026-04-08T15:30:01Z' '202': - description: Challenge issued. Build an API-key stamp over `payloadToSign` with the session API keypair of an existing verified credential on the same internal account, then send that full stamp as `Grid-Wallet-Signature` and echo `requestId` as `Request-Id` on the retry. + description: |- + Non-terminal response carrying one of two bodies, distinguished by their fields. A signed-retry challenge (`payloadToSign` plus `requestId`) is returned on the initial call: build an API-key stamp over `payloadToSign` with the session API keypair of an existing verified credential on the same internal account, then send that full stamp as `Grid-Wallet-Signature` and echo `requestId` as `Request-Id` on the retry. + + A still-processing body (`status: PENDING`) is returned when the operation ran optimistically in line but has fallen back to asynchronous processing — this can occur on the signed retry. Re-send the identical request, unchanged, on a short interval until it returns the terminal `201`. Do not add or alter a signature; the request is simply repeated as-is. content: application/json: schema: - $ref: '#/components/schemas/AuthSignedRequestChallenge' + $ref: '#/components/schemas/AuthSignedRequestChallengeOrProcessingPending' examples: emailOtp: summary: Additional email OTP credential challenge @@ -5673,6 +5686,10 @@ paths: payloadToSign: '{"organizationId":"org_2m9F...","parameters":{"authenticators":[{"attestation":{"attestationObject":"o2NmbXRk...","clientDataJson":"eyJjaGFsbGVuZ2UiOiJBcktRa...","credentialId":"AdKXJEch1aV5Wo7bj7qLHskVY4OoNaj9qu8TPdJ7kSAgUeRxWNngXlcNIGt4gexZGKVGcqZpqqWordXb_he1izY"},"authenticatorName":"iPhone Face-ID","challenge":"ArkQi2yAYHPlgnJNFBlneIwchQdWXBOTrdB-AmMUB21Lx","transports":["internal","hybrid"]}],"userId":"user_2m9F..."},"timestampMs":"1775681700000","type":"ACTIVITY_TYPE_CREATE_AUTHENTICATORS_V2"}' requestId: Request:7c4a8d09-ca37-4e3e-9e0d-8c2b3e9a1f21 expiresAt: '2026-04-08T15:35:00Z' + processingPending: + summary: Operation still processing (re-send the identical request) + value: + status: PENDING '400': description: Bad request. Returned with `EMAIL_OTP_CREDENTIAL_ALREADY_EXISTS` when registering an email OTP credential while one already exists, `SMS_OTP_CREDENTIAL_ALREADY_EXISTS` when registering an SMS OTP credential while one already exists, `PASSKEY_CREDENTIAL_ALREADY_EXISTS` when registering a passkey whose WebAuthn credentialId is already attached to the internal account, or `INVALID_INPUT` when an OAuth `oidcToken` is malformed or has an unsupported issuer. content: @@ -5925,11 +5942,14 @@ paths: schema: $ref: '#/components/schemas/AuthSession' '202': - description: Verification challenge issued. Returned only for OTP credentials, on the first leg of the secure OTP login flow. Build an API-key stamp over `payloadToSign` (the `verificationToken`) with the TEK keypair the client generated for this login, then resubmit the same request with that full stamp as `Grid-Wallet-Signature` and `requestId` echoed as `Request-Id` to receive the issued session on the signed retry. + description: |- + Non-terminal response carrying one of two bodies, distinguished by their fields. A signed-retry challenge (`payloadToSign` plus `requestId`) is returned for OTP credentials on the first leg of the secure OTP login flow: build an API-key stamp over `payloadToSign` (the `verificationToken`) with the TEK keypair the client generated for this login, then resubmit the same request with that full stamp as `Grid-Wallet-Signature` and `requestId` echoed as `Request-Id` to receive the issued session on the signed retry. + + A still-processing body (`status: PENDING`) is returned when the operation ran optimistically in line but has fallen back to asynchronous processing — this can occur on the OTP signed retry or on `OAUTH`/`PASSKEY` verification. Re-send the identical request, unchanged, on a short interval until it returns the terminal `200`. Do not add or alter a signature; the request is simply repeated as-is. content: application/json: schema: - $ref: '#/components/schemas/AuthSignedRequestChallenge' + $ref: '#/components/schemas/AuthSignedRequestChallengeOrProcessingPending' examples: emailOtp: summary: Email OTP verification challenge (sign and retry) @@ -5938,6 +5958,10 @@ paths: payloadToSign: eyJhbGciOiJFUzI1NiIsImtpZCI6InR1cm5rZXkifQ.eyJzdWIiOiJUWnk2NkVPa1RGYTd2NkpXZ0VxaVgyZGFXOENXc2pMQzVDVU9aRUlGY3hzIiwiaWF0IjoxNzc5NDA3MjIxLCJleHAiOjE3Nzk0MTA4MjF9.gKX9MWYGkw8Y55bgzsgrRftvUHFruIe8yu0w9Kpjp5qnrZnXcTV71WVoltGPsr015IY_oRTOkIFLHmiGNG9zBw requestId: Request:7c4a8d09-ca37-4e3e-9e0d-8c2b3e9a1f21 expiresAt: '2026-04-08T15:35:00Z' + processingPending: + summary: Operation still processing (re-send the identical request) + value: + status: PENDING '400': description: Bad request content: @@ -6045,6 +6069,12 @@ paths: challenge: 6b35a4c41d9aa7a2a0e742f9f9e7a1c2d65a2db33a3fb748f6d4f1ce78d9a729 requestId: Request:7c4a8d09-ca37-4e3e-9e0d-8c2b3e9a1f21 expiresAt: '2026-04-08T15:35:00Z' + '202': + description: 'The operation is still processing. Grid ran it optimistically in line but it has fallen back to asynchronous processing (for example, while a new OTP is being issued or a passkey reauthentication challenge is being prepared). No action beyond retrying is required: re-send the identical request — same method, path, body, and headers — on a short interval until it returns the terminal `200`. The response body carries `status: PENDING` and nothing else to act on.' + content: + application/json: + schema: + $ref: '#/components/schemas/ProcessingPendingResponse' '400': description: Bad request content: @@ -6264,11 +6294,14 @@ paths: updatedAt: '2026-04-08T15:35:00Z' expiresAt: '2026-04-08T15:50:00Z' '202': - description: Challenge issued. The response contains `payloadToSign` plus a `requestId`. Build an API-key stamp over `payloadToSign` with the current session API keypair, then echo `requestId` on the signed retry. + description: |- + Non-terminal response carrying one of two bodies, distinguished by their fields. A signed-retry challenge (`payloadToSign` plus `requestId`) is returned on the initial call: build an API-key stamp over `payloadToSign` with the current session API keypair, then echo `requestId` on the signed retry. + + A still-processing body (`status: PENDING`) is returned when the operation ran optimistically in line but has fallen back to asynchronous processing — this can occur on the signed retry. Re-send the identical request, unchanged, on a short interval until it returns the terminal `201`. Do not add or alter a signature; the request is simply repeated as-is. content: application/json: schema: - $ref: '#/components/schemas/SignedRequestChallenge' + $ref: '#/components/schemas/SignedRequestChallengeOrProcessingPending' examples: challenge: summary: Session refresh challenge @@ -6276,6 +6309,10 @@ paths: payloadToSign: '{"organizationId":"org_abc123","parameters":{"targetPublicKey":"04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2"},"timestampMs":"1746736509954","type":"ACTIVITY_TYPE_CREATE_READ_WRITE_SESSION_V2"}' requestId: Request:019542f5-b3e7-1d02-0000-000000000010 expiresAt: '2026-04-08T15:35:00Z' + processingPending: + summary: Operation still processing (re-send the identical request) + value: + status: PENDING '400': description: Bad request content: @@ -6369,11 +6406,14 @@ paths: createdAt: '2026-04-08T15:30:01Z' updatedAt: '2026-04-08T15:30:42Z' '202': - description: Challenge issued for the next leg. Stamp `payloadToSign` and retry the same request with `Grid-Wallet-Signature` and `Request-Id`. + description: |- + Non-terminal response carrying one of two bodies, distinguished by their fields. A signed-retry challenge (`payloadToSign` plus `requestId`) is returned for the next leg of the flow: stamp `payloadToSign` and retry the same request with `Grid-Wallet-Signature` and `Request-Id`. + + A still-processing body (`status: PENDING`) is returned when the operation ran optimistically in line but has fallen back to asynchronous processing — this can occur on either signed leg. Re-send the identical request, unchanged, on a short interval until it returns either the next signed-retry challenge or the terminal `201`. Do not add or alter a signature; the request is simply repeated as-is. content: application/json: schema: - $ref: '#/components/schemas/DelegatedKeySignedRequestChallenge' + $ref: '#/components/schemas/DelegatedKeySignedRequestChallengeOrProcessingPending' '400': description: Bad request content: @@ -6514,6 +6554,12 @@ paths: type: string example: DelegatedKey:019542f5-b3e7-1d02-0000-000000000021 responses: + '202': + description: 'The revocation is still processing. Grid ran it optimistically in line but it has fallen back to asynchronous processing. Re-send the identical `DELETE` request — same method, path, and headers — on a short interval until it returns the terminal `204`. The response body carries `status: PENDING` and nothing else to act on.' + content: + application/json: + schema: + $ref: '#/components/schemas/ProcessingPendingResponse' '204': description: Delegated key revoked. The key can no longer authorize signing. '400': @@ -13332,6 +13378,25 @@ components: format: date-time description: Timestamp after which this challenge is no longer valid. The signed retry must be submitted before this time. example: '2026-04-08T15:35:00Z' + ProcessingPendingResponse: + title: Processing Pending + type: object + required: + - status + description: Non-terminal response body returned with HTTP `202` when an Embedded Wallet operation is still processing. These operations run optimistically in line and usually complete within the request, but can fall back to asynchronous processing; when that happens Grid returns this body with `202`. The request has been accepted and is progressing — re-send the identical request (same method, path, body, and headers) to check on and complete it. Keep re-sending on a short interval until the operation resolves to its terminal success response (`200`/`201`/`204`, depending on the endpoint) or to a `4xx`/`5xx` error. Each re-send is idempotent and continues the same in-flight operation rather than starting a new one, so this body carries no `payloadToSign` and no request identifier — there is nothing to sign and nothing new to correlate, the request is simply repeated unchanged. + properties: + status: + type: string + enum: + - PENDING + description: Always `PENDING`. Signals that the operation has not reached a terminal state yet and that the identical request should be re-sent, unchanged, to check for completion. + example: PENDING + SignedRequestChallengeOrProcessingPending: + title: Signed Request Challenge Or Processing Pending + description: 'The two possible `202` bodies on Embedded Wallet endpoints that use the signed-retry flow. Either a `SignedRequestChallenge` — carrying `payloadToSign`, which the client stamps and re-sends with `Grid-Wallet-Signature` and `Request-Id` — or a `ProcessingPendingResponse` (`status: PENDING`), meaning the operation is still processing and the identical request should be re-sent unchanged until it returns a terminal response. Distinguish the two by their fields: a `payloadToSign` means sign and retry; a `status` of `PENDING` means re-send unchanged and keep polling.' + anyOf: + - $ref: '#/components/schemas/SignedRequestChallenge' + - $ref: '#/components/schemas/ProcessingPendingResponse' Error424: type: object required: @@ -22747,6 +22812,12 @@ components: type: $ref: '#/components/schemas/AuthMethodType' description: 'Credential type relevant to this challenge: the credential type being added (`POST /auth/credentials`), revoked (`DELETE /auth/credentials/{id}`), or authenticated (`EMAIL_OTP` / `SMS_OTP` branch of `POST /auth/credentials/{id}/verify`). For session revocation, this is the type of credential that issued the session (`DELETE /auth/sessions/{id}`).' + AuthSignedRequestChallengeOrProcessingPending: + title: Authentication Signed Request Challenge Or Processing Pending + description: 'The two possible `202` bodies on Embedded Wallet Auth endpoints that use the signed-retry flow. Either an `AuthSignedRequestChallenge` — carrying `payloadToSign` plus the credential `type`, which the client stamps and re-sends with `Grid-Wallet-Signature` and `Request-Id` — or a `ProcessingPendingResponse` (`status: PENDING`), meaning the operation is still processing and the identical request should be re-sent unchanged until it returns a terminal response. Distinguish the two by their fields: a `payloadToSign` means sign and retry; a `status` of `PENDING` means re-send unchanged and keep polling.' + anyOf: + - $ref: '#/components/schemas/AuthSignedRequestChallenge' + - $ref: '#/components/schemas/ProcessingPendingResponse' AuthCredentialVerifyRequest: type: object required: @@ -23118,6 +23189,12 @@ components: description: 202 response returned from the delegated-key endpoints. Stamp `payloadToSign` with the session API keypair of a verified credential on the delegated key's Embedded Wallet funding account, then retry the same request with the full stamp in `Grid-Wallet-Signature` and the `requestId` echoed in `Request-Id`. allOf: - $ref: '#/components/schemas/SignedRequestChallenge' + DelegatedKeySignedRequestChallengeOrProcessingPending: + title: Delegated Key Signed Request Challenge Or Processing Pending + description: 'The two possible `202` bodies on the delegated-key create flow. Either a `DelegatedKeySignedRequestChallenge` — carrying `payloadToSign` for the next leg, which the client stamps and re-sends with `Grid-Wallet-Signature` and `Request-Id` — or a `ProcessingPendingResponse` (`status: PENDING`), meaning the operation is still processing and the identical request should be re-sent unchanged until it returns the next challenge or a terminal response. Distinguish the two by their fields: a `payloadToSign` means sign and retry; a `status` of `PENDING` means re-send unchanged and keep polling.' + anyOf: + - $ref: '#/components/schemas/DelegatedKeySignedRequestChallenge' + - $ref: '#/components/schemas/ProcessingPendingResponse' AgentPermission: type: string enum: diff --git a/mintlify/snippets/global-accounts/authentication.mdx b/mintlify/snippets/global-accounts/authentication.mdx index 1f91faeaa..6f0223de7 100644 --- a/mintlify/snippets/global-accounts/authentication.mdx +++ b/mintlify/snippets/global-accounts/authentication.mdx @@ -673,6 +673,25 @@ Key rules: - The retry must reach Grid before `expiresAt` (typically 5 minutes from issue). - The `requestId` is returned as `Request:` and is single-use; reusing one yields `401`. +### Still-processing responses (202 PENDING) + +Global Account operations that touch the wallet — sign-in (`POST /auth/credentials/{id}/verify`), the OTP or passkey challenge (`POST /auth/credentials/{id}/challenge`), adding or revoking a credential, refreshing a session, exporting a wallet, updating a wallet-tied customer email or phone, and creating or revoking a delegated key — run optimistically in line and usually finish within the request. When one can't finish synchronously it falls back to asynchronous processing, and Grid returns **HTTP `202` with `{ "status": "PENDING" }`** instead of the terminal response. This is not an error, and it is not the signed-retry challenge above — it means the request has been accepted and is still in flight. + +When you receive a `202 PENDING`, **re-send the identical request** — same method, path, body, and headers — on a short interval until it returns a terminal `200`/`201`/`204` (or a `4xx`/`5xx` error): + +```json +{ + "status": "PENDING" +} +``` + +Key rules: + +- Repeat the request **exactly as you last sent it**. On the initial leg that is the unsigned request; on a signed retry that is the same request *with* its `Grid-Wallet-Signature` and `Request-Id`. A `202 PENDING` never asks you to sign anything new — there is no `payloadToSign` to stamp. +- Re-sending an in-flight signed request is the expected idempotent resubmit — it continues the same operation and is **not** the reused-`requestId` case that returns `401` (that applies only once the request has reached a terminal response). +- Tell the two `202` bodies apart by their fields: a `payloadToSign` means "sign and retry"; a `status` of `PENDING` means "re-send unchanged and keep polling". +- Poll on a short, bounded interval (for example, every 1–2 seconds with a sensible cap) rather than in a tight loop. + ### Add an additional credential Requires an active session on an *existing* credential on the same account. The first call uses the normal credential-create body; Grid detects the pre-existing credential and responds `202` instead of `201`. `OAUTH` and `PASSKEY` are the typical additional credential types. `EMAIL_OTP` can be added back only after the existing email OTP credential has been removed, because each account supports one. diff --git a/openapi.yaml b/openapi.yaml index d2332c99e..753d2c463 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -744,11 +744,14 @@ paths: schema: $ref: '#/components/schemas/CustomerOneOf' '202': - description: Challenge issued for an Embedded Wallet email or SMS auth phone update. The response contains `payloadToSign` plus a `requestId`. Build an API-key stamp over `payloadToSign` with the session API keypair from a verified authentication credential on one of the customer's tied Embedded Wallets, then retry the same request with `Grid-Wallet-Signature` and `Request-Id`. + description: |- + Non-terminal response for an Embedded Wallet email or SMS auth phone update, carrying one of two bodies distinguished by their fields. A signed-retry challenge (`payloadToSign` plus `requestId`) is returned on the initial call: build an API-key stamp over `payloadToSign` with the session API keypair from a verified authentication credential on one of the customer's tied Embedded Wallets, then retry the same request with `Grid-Wallet-Signature` and `Request-Id`. + + A still-processing body (`status: PENDING`) is returned when the operation ran optimistically in line but has fallen back to asynchronous processing — this can occur on the signed retry. Re-send the identical request, unchanged, on a short interval until it returns the terminal `200`. Do not add or alter a signature; the request is simply repeated as-is. content: application/json: schema: - $ref: '#/components/schemas/SignedRequestChallenge' + $ref: '#/components/schemas/SignedRequestChallengeOrProcessingPending' examples: embeddedWalletEmailUpdate: summary: Embedded Wallet customer email update challenge @@ -762,6 +765,10 @@ paths: payloadToSign: '{"organizationId":"org_2m9F...","parameters":{"userId":"user_2m9F...","userPhoneNumber":"+14155559876"},"timestampMs":"1775681700000","type":"ACTIVITY_TYPE_UPDATE_USER_PHONE_NUMBER"}' requestId: Request:019542f5-b3e7-1d02-0000-000000000011 expiresAt: '2026-04-08T15:35:00Z' + processingPending: + summary: Operation still processing (re-send the identical request) + value: + status: PENDING '400': description: Bad request content: @@ -5497,11 +5504,14 @@ paths: schema: $ref: '#/components/schemas/InternalAccountExportResponse' '202': - description: Challenge issued. The response contains `payloadToSign` (which binds the submitted `clientPublicKey`) plus a `requestId`. Build an API-key stamp over `payloadToSign` with the session API keypair and echo `requestId` on the retry. + description: |- + Non-terminal response carrying one of two bodies, distinguished by their fields. A signed-retry challenge (`payloadToSign`, which binds the submitted `clientPublicKey`, plus a `requestId`) is returned on the initial call: build an API-key stamp over `payloadToSign` with the session API keypair and echo `requestId` on the retry. + + A still-processing body (`status: PENDING`) is returned when the operation ran optimistically in line but has fallen back to asynchronous processing — this can occur on the signed retry. Re-send the identical request, unchanged (including the same `clientPublicKey`), on a short interval until it returns the terminal `200`. Do not add or alter a signature; the request is simply repeated as-is. content: application/json: schema: - $ref: '#/components/schemas/SignedRequestChallenge' + $ref: '#/components/schemas/SignedRequestChallengeOrProcessingPending' '400': description: Bad request content: @@ -5639,11 +5649,14 @@ paths: createdAt: '2026-04-08T15:30:01Z' updatedAt: '2026-04-08T15:30:01Z' '202': - description: Challenge issued. Build an API-key stamp over `payloadToSign` with the session API keypair of an existing verified credential on the same internal account, then send that full stamp as `Grid-Wallet-Signature` and echo `requestId` as `Request-Id` on the retry. + description: |- + Non-terminal response carrying one of two bodies, distinguished by their fields. A signed-retry challenge (`payloadToSign` plus `requestId`) is returned on the initial call: build an API-key stamp over `payloadToSign` with the session API keypair of an existing verified credential on the same internal account, then send that full stamp as `Grid-Wallet-Signature` and echo `requestId` as `Request-Id` on the retry. + + A still-processing body (`status: PENDING`) is returned when the operation ran optimistically in line but has fallen back to asynchronous processing — this can occur on the signed retry. Re-send the identical request, unchanged, on a short interval until it returns the terminal `201`. Do not add or alter a signature; the request is simply repeated as-is. content: application/json: schema: - $ref: '#/components/schemas/AuthSignedRequestChallenge' + $ref: '#/components/schemas/AuthSignedRequestChallengeOrProcessingPending' examples: emailOtp: summary: Additional email OTP credential challenge @@ -5673,6 +5686,10 @@ paths: payloadToSign: '{"organizationId":"org_2m9F...","parameters":{"authenticators":[{"attestation":{"attestationObject":"o2NmbXRk...","clientDataJson":"eyJjaGFsbGVuZ2UiOiJBcktRa...","credentialId":"AdKXJEch1aV5Wo7bj7qLHskVY4OoNaj9qu8TPdJ7kSAgUeRxWNngXlcNIGt4gexZGKVGcqZpqqWordXb_he1izY"},"authenticatorName":"iPhone Face-ID","challenge":"ArkQi2yAYHPlgnJNFBlneIwchQdWXBOTrdB-AmMUB21Lx","transports":["internal","hybrid"]}],"userId":"user_2m9F..."},"timestampMs":"1775681700000","type":"ACTIVITY_TYPE_CREATE_AUTHENTICATORS_V2"}' requestId: Request:7c4a8d09-ca37-4e3e-9e0d-8c2b3e9a1f21 expiresAt: '2026-04-08T15:35:00Z' + processingPending: + summary: Operation still processing (re-send the identical request) + value: + status: PENDING '400': description: Bad request. Returned with `EMAIL_OTP_CREDENTIAL_ALREADY_EXISTS` when registering an email OTP credential while one already exists, `SMS_OTP_CREDENTIAL_ALREADY_EXISTS` when registering an SMS OTP credential while one already exists, `PASSKEY_CREDENTIAL_ALREADY_EXISTS` when registering a passkey whose WebAuthn credentialId is already attached to the internal account, or `INVALID_INPUT` when an OAuth `oidcToken` is malformed or has an unsupported issuer. content: @@ -5925,11 +5942,14 @@ paths: schema: $ref: '#/components/schemas/AuthSession' '202': - description: Verification challenge issued. Returned only for OTP credentials, on the first leg of the secure OTP login flow. Build an API-key stamp over `payloadToSign` (the `verificationToken`) with the TEK keypair the client generated for this login, then resubmit the same request with that full stamp as `Grid-Wallet-Signature` and `requestId` echoed as `Request-Id` to receive the issued session on the signed retry. + description: |- + Non-terminal response carrying one of two bodies, distinguished by their fields. A signed-retry challenge (`payloadToSign` plus `requestId`) is returned for OTP credentials on the first leg of the secure OTP login flow: build an API-key stamp over `payloadToSign` (the `verificationToken`) with the TEK keypair the client generated for this login, then resubmit the same request with that full stamp as `Grid-Wallet-Signature` and `requestId` echoed as `Request-Id` to receive the issued session on the signed retry. + + A still-processing body (`status: PENDING`) is returned when the operation ran optimistically in line but has fallen back to asynchronous processing — this can occur on the OTP signed retry or on `OAUTH`/`PASSKEY` verification. Re-send the identical request, unchanged, on a short interval until it returns the terminal `200`. Do not add or alter a signature; the request is simply repeated as-is. content: application/json: schema: - $ref: '#/components/schemas/AuthSignedRequestChallenge' + $ref: '#/components/schemas/AuthSignedRequestChallengeOrProcessingPending' examples: emailOtp: summary: Email OTP verification challenge (sign and retry) @@ -5938,6 +5958,10 @@ paths: payloadToSign: eyJhbGciOiJFUzI1NiIsImtpZCI6InR1cm5rZXkifQ.eyJzdWIiOiJUWnk2NkVPa1RGYTd2NkpXZ0VxaVgyZGFXOENXc2pMQzVDVU9aRUlGY3hzIiwiaWF0IjoxNzc5NDA3MjIxLCJleHAiOjE3Nzk0MTA4MjF9.gKX9MWYGkw8Y55bgzsgrRftvUHFruIe8yu0w9Kpjp5qnrZnXcTV71WVoltGPsr015IY_oRTOkIFLHmiGNG9zBw requestId: Request:7c4a8d09-ca37-4e3e-9e0d-8c2b3e9a1f21 expiresAt: '2026-04-08T15:35:00Z' + processingPending: + summary: Operation still processing (re-send the identical request) + value: + status: PENDING '400': description: Bad request content: @@ -6045,6 +6069,12 @@ paths: challenge: 6b35a4c41d9aa7a2a0e742f9f9e7a1c2d65a2db33a3fb748f6d4f1ce78d9a729 requestId: Request:7c4a8d09-ca37-4e3e-9e0d-8c2b3e9a1f21 expiresAt: '2026-04-08T15:35:00Z' + '202': + description: 'The operation is still processing. Grid ran it optimistically in line but it has fallen back to asynchronous processing (for example, while a new OTP is being issued or a passkey reauthentication challenge is being prepared). No action beyond retrying is required: re-send the identical request — same method, path, body, and headers — on a short interval until it returns the terminal `200`. The response body carries `status: PENDING` and nothing else to act on.' + content: + application/json: + schema: + $ref: '#/components/schemas/ProcessingPendingResponse' '400': description: Bad request content: @@ -6264,11 +6294,14 @@ paths: updatedAt: '2026-04-08T15:35:00Z' expiresAt: '2026-04-08T15:50:00Z' '202': - description: Challenge issued. The response contains `payloadToSign` plus a `requestId`. Build an API-key stamp over `payloadToSign` with the current session API keypair, then echo `requestId` on the signed retry. + description: |- + Non-terminal response carrying one of two bodies, distinguished by their fields. A signed-retry challenge (`payloadToSign` plus `requestId`) is returned on the initial call: build an API-key stamp over `payloadToSign` with the current session API keypair, then echo `requestId` on the signed retry. + + A still-processing body (`status: PENDING`) is returned when the operation ran optimistically in line but has fallen back to asynchronous processing — this can occur on the signed retry. Re-send the identical request, unchanged, on a short interval until it returns the terminal `201`. Do not add or alter a signature; the request is simply repeated as-is. content: application/json: schema: - $ref: '#/components/schemas/SignedRequestChallenge' + $ref: '#/components/schemas/SignedRequestChallengeOrProcessingPending' examples: challenge: summary: Session refresh challenge @@ -6276,6 +6309,10 @@ paths: payloadToSign: '{"organizationId":"org_abc123","parameters":{"targetPublicKey":"04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2"},"timestampMs":"1746736509954","type":"ACTIVITY_TYPE_CREATE_READ_WRITE_SESSION_V2"}' requestId: Request:019542f5-b3e7-1d02-0000-000000000010 expiresAt: '2026-04-08T15:35:00Z' + processingPending: + summary: Operation still processing (re-send the identical request) + value: + status: PENDING '400': description: Bad request content: @@ -6369,11 +6406,14 @@ paths: createdAt: '2026-04-08T15:30:01Z' updatedAt: '2026-04-08T15:30:42Z' '202': - description: Challenge issued for the next leg. Stamp `payloadToSign` and retry the same request with `Grid-Wallet-Signature` and `Request-Id`. + description: |- + Non-terminal response carrying one of two bodies, distinguished by their fields. A signed-retry challenge (`payloadToSign` plus `requestId`) is returned for the next leg of the flow: stamp `payloadToSign` and retry the same request with `Grid-Wallet-Signature` and `Request-Id`. + + A still-processing body (`status: PENDING`) is returned when the operation ran optimistically in line but has fallen back to asynchronous processing — this can occur on either signed leg. Re-send the identical request, unchanged, on a short interval until it returns either the next signed-retry challenge or the terminal `201`. Do not add or alter a signature; the request is simply repeated as-is. content: application/json: schema: - $ref: '#/components/schemas/DelegatedKeySignedRequestChallenge' + $ref: '#/components/schemas/DelegatedKeySignedRequestChallengeOrProcessingPending' '400': description: Bad request content: @@ -6514,6 +6554,12 @@ paths: type: string example: DelegatedKey:019542f5-b3e7-1d02-0000-000000000021 responses: + '202': + description: 'The revocation is still processing. Grid ran it optimistically in line but it has fallen back to asynchronous processing. Re-send the identical `DELETE` request — same method, path, and headers — on a short interval until it returns the terminal `204`. The response body carries `status: PENDING` and nothing else to act on.' + content: + application/json: + schema: + $ref: '#/components/schemas/ProcessingPendingResponse' '204': description: Delegated key revoked. The key can no longer authorize signing. '400': @@ -13332,6 +13378,25 @@ components: format: date-time description: Timestamp after which this challenge is no longer valid. The signed retry must be submitted before this time. example: '2026-04-08T15:35:00Z' + ProcessingPendingResponse: + title: Processing Pending + type: object + required: + - status + description: Non-terminal response body returned with HTTP `202` when an Embedded Wallet operation is still processing. These operations run optimistically in line and usually complete within the request, but can fall back to asynchronous processing; when that happens Grid returns this body with `202`. The request has been accepted and is progressing — re-send the identical request (same method, path, body, and headers) to check on and complete it. Keep re-sending on a short interval until the operation resolves to its terminal success response (`200`/`201`/`204`, depending on the endpoint) or to a `4xx`/`5xx` error. Each re-send is idempotent and continues the same in-flight operation rather than starting a new one, so this body carries no `payloadToSign` and no request identifier — there is nothing to sign and nothing new to correlate, the request is simply repeated unchanged. + properties: + status: + type: string + enum: + - PENDING + description: Always `PENDING`. Signals that the operation has not reached a terminal state yet and that the identical request should be re-sent, unchanged, to check for completion. + example: PENDING + SignedRequestChallengeOrProcessingPending: + title: Signed Request Challenge Or Processing Pending + description: 'The two possible `202` bodies on Embedded Wallet endpoints that use the signed-retry flow. Either a `SignedRequestChallenge` — carrying `payloadToSign`, which the client stamps and re-sends with `Grid-Wallet-Signature` and `Request-Id` — or a `ProcessingPendingResponse` (`status: PENDING`), meaning the operation is still processing and the identical request should be re-sent unchanged until it returns a terminal response. Distinguish the two by their fields: a `payloadToSign` means sign and retry; a `status` of `PENDING` means re-send unchanged and keep polling.' + anyOf: + - $ref: '#/components/schemas/SignedRequestChallenge' + - $ref: '#/components/schemas/ProcessingPendingResponse' Error424: type: object required: @@ -22747,6 +22812,12 @@ components: type: $ref: '#/components/schemas/AuthMethodType' description: 'Credential type relevant to this challenge: the credential type being added (`POST /auth/credentials`), revoked (`DELETE /auth/credentials/{id}`), or authenticated (`EMAIL_OTP` / `SMS_OTP` branch of `POST /auth/credentials/{id}/verify`). For session revocation, this is the type of credential that issued the session (`DELETE /auth/sessions/{id}`).' + AuthSignedRequestChallengeOrProcessingPending: + title: Authentication Signed Request Challenge Or Processing Pending + description: 'The two possible `202` bodies on Embedded Wallet Auth endpoints that use the signed-retry flow. Either an `AuthSignedRequestChallenge` — carrying `payloadToSign` plus the credential `type`, which the client stamps and re-sends with `Grid-Wallet-Signature` and `Request-Id` — or a `ProcessingPendingResponse` (`status: PENDING`), meaning the operation is still processing and the identical request should be re-sent unchanged until it returns a terminal response. Distinguish the two by their fields: a `payloadToSign` means sign and retry; a `status` of `PENDING` means re-send unchanged and keep polling.' + anyOf: + - $ref: '#/components/schemas/AuthSignedRequestChallenge' + - $ref: '#/components/schemas/ProcessingPendingResponse' AuthCredentialVerifyRequest: type: object required: @@ -23118,6 +23189,12 @@ components: description: 202 response returned from the delegated-key endpoints. Stamp `payloadToSign` with the session API keypair of a verified credential on the delegated key's Embedded Wallet funding account, then retry the same request with the full stamp in `Grid-Wallet-Signature` and the `requestId` echoed in `Request-Id`. allOf: - $ref: '#/components/schemas/SignedRequestChallenge' + DelegatedKeySignedRequestChallengeOrProcessingPending: + title: Delegated Key Signed Request Challenge Or Processing Pending + description: 'The two possible `202` bodies on the delegated-key create flow. Either a `DelegatedKeySignedRequestChallenge` — carrying `payloadToSign` for the next leg, which the client stamps and re-sends with `Grid-Wallet-Signature` and `Request-Id` — or a `ProcessingPendingResponse` (`status: PENDING`), meaning the operation is still processing and the identical request should be re-sent unchanged until it returns the next challenge or a terminal response. Distinguish the two by their fields: a `payloadToSign` means sign and retry; a `status` of `PENDING` means re-send unchanged and keep polling.' + anyOf: + - $ref: '#/components/schemas/DelegatedKeySignedRequestChallenge' + - $ref: '#/components/schemas/ProcessingPendingResponse' AgentPermission: type: string enum: diff --git a/openapi/components/schemas/auth/AuthSignedRequestChallengeOrProcessingPending.yaml b/openapi/components/schemas/auth/AuthSignedRequestChallengeOrProcessingPending.yaml new file mode 100644 index 000000000..5beeff56d --- /dev/null +++ b/openapi/components/schemas/auth/AuthSignedRequestChallengeOrProcessingPending.yaml @@ -0,0 +1,14 @@ +title: Authentication Signed Request Challenge Or Processing Pending +description: >- + The two possible `202` bodies on Embedded Wallet Auth endpoints that use the + signed-retry flow. Either an `AuthSignedRequestChallenge` — carrying + `payloadToSign` plus the credential `type`, which the client stamps and + re-sends with `Grid-Wallet-Signature` and `Request-Id` — or a + `ProcessingPendingResponse` (`status: PENDING`), meaning the operation is + still processing and the identical request should be re-sent unchanged until + it returns a terminal response. Distinguish the two by their fields: a + `payloadToSign` means sign and retry; a `status` of `PENDING` means re-send + unchanged and keep polling. +anyOf: + - $ref: ./AuthSignedRequestChallenge.yaml + - $ref: ../common/ProcessingPendingResponse.yaml diff --git a/openapi/components/schemas/auth/DelegatedKeySignedRequestChallengeOrProcessingPending.yaml b/openapi/components/schemas/auth/DelegatedKeySignedRequestChallengeOrProcessingPending.yaml new file mode 100644 index 000000000..341c0f2bf --- /dev/null +++ b/openapi/components/schemas/auth/DelegatedKeySignedRequestChallengeOrProcessingPending.yaml @@ -0,0 +1,13 @@ +title: Delegated Key Signed Request Challenge Or Processing Pending +description: >- + The two possible `202` bodies on the delegated-key create flow. Either a + `DelegatedKeySignedRequestChallenge` — carrying `payloadToSign` for the next + leg, which the client stamps and re-sends with `Grid-Wallet-Signature` and + `Request-Id` — or a `ProcessingPendingResponse` (`status: PENDING`), meaning + the operation is still processing and the identical request should be re-sent + unchanged until it returns the next challenge or a terminal response. + Distinguish the two by their fields: a `payloadToSign` means sign and retry; a + `status` of `PENDING` means re-send unchanged and keep polling. +anyOf: + - $ref: ./DelegatedKeySignedRequestChallenge.yaml + - $ref: ../common/ProcessingPendingResponse.yaml diff --git a/openapi/components/schemas/common/ProcessingPendingResponse.yaml b/openapi/components/schemas/common/ProcessingPendingResponse.yaml new file mode 100644 index 000000000..60564f5ef --- /dev/null +++ b/openapi/components/schemas/common/ProcessingPendingResponse.yaml @@ -0,0 +1,27 @@ +title: Processing Pending +type: object +required: + - status +description: >- + Non-terminal response body returned with HTTP `202` when an Embedded Wallet + operation is still processing. These operations run optimistically in line and + usually complete within the request, but can fall back to asynchronous + processing; when that happens Grid returns this body with `202`. The request + has been accepted and is progressing — re-send the identical request (same + method, path, body, and headers) to check on and complete it. Keep re-sending + on a short interval until the operation resolves to its terminal success + response (`200`/`201`/`204`, depending on the endpoint) or to a `4xx`/`5xx` + error. Each re-send is idempotent and continues the same in-flight operation + rather than starting a new one, so this body carries no `payloadToSign` and no + request identifier — there is nothing to sign and nothing new to correlate, + the request is simply repeated unchanged. +properties: + status: + type: string + enum: + - PENDING + description: >- + Always `PENDING`. Signals that the operation has not reached a terminal + state yet and that the identical request should be re-sent, unchanged, to + check for completion. + example: PENDING diff --git a/openapi/components/schemas/common/SignedRequestChallengeOrProcessingPending.yaml b/openapi/components/schemas/common/SignedRequestChallengeOrProcessingPending.yaml new file mode 100644 index 000000000..b1a43bfdc --- /dev/null +++ b/openapi/components/schemas/common/SignedRequestChallengeOrProcessingPending.yaml @@ -0,0 +1,13 @@ +title: Signed Request Challenge Or Processing Pending +description: >- + The two possible `202` bodies on Embedded Wallet endpoints that use the + signed-retry flow. Either a `SignedRequestChallenge` — carrying + `payloadToSign`, which the client stamps and re-sends with + `Grid-Wallet-Signature` and `Request-Id` — or a `ProcessingPendingResponse` + (`status: PENDING`), meaning the operation is still processing and the + identical request should be re-sent unchanged until it returns a terminal + response. Distinguish the two by their fields: a `payloadToSign` means sign + and retry; a `status` of `PENDING` means re-send unchanged and keep polling. +anyOf: + - $ref: ./SignedRequestChallenge.yaml + - $ref: ./ProcessingPendingResponse.yaml diff --git a/openapi/paths/auth/auth_credentials.yaml b/openapi/paths/auth/auth_credentials.yaml index 7a16ed121..144899295 100644 --- a/openapi/paths/auth/auth_credentials.yaml +++ b/openapi/paths/auth/auth_credentials.yaml @@ -152,15 +152,25 @@ post: updatedAt: '2026-04-08T15:30:01Z' '202': description: >- - Challenge issued. Build an API-key stamp over `payloadToSign` with - the session API keypair of an existing verified credential on the - same internal account, then send that full stamp as - `Grid-Wallet-Signature` and echo `requestId` as `Request-Id` on - the retry. + Non-terminal response carrying one of two bodies, distinguished by + their fields. A signed-retry challenge (`payloadToSign` plus + `requestId`) is returned on the initial call: build an API-key stamp + over `payloadToSign` with the session API keypair of an existing + verified credential on the same internal account, then send that full + stamp as `Grid-Wallet-Signature` and echo `requestId` as `Request-Id` + on the retry. + + + A still-processing body (`status: PENDING`) is returned when the + operation ran optimistically in line but has fallen back to + asynchronous processing — this can occur on the signed retry. Re-send + the identical request, unchanged, on a short interval until it returns + the terminal `201`. Do not add or alter a signature; the request is + simply repeated as-is. content: application/json: schema: - $ref: ../../components/schemas/auth/AuthSignedRequestChallenge.yaml + $ref: ../../components/schemas/auth/AuthSignedRequestChallengeOrProcessingPending.yaml examples: emailOtp: summary: Additional email OTP credential challenge @@ -190,6 +200,10 @@ post: payloadToSign: '{"organizationId":"org_2m9F...","parameters":{"authenticators":[{"attestation":{"attestationObject":"o2NmbXRk...","clientDataJson":"eyJjaGFsbGVuZ2UiOiJBcktRa...","credentialId":"AdKXJEch1aV5Wo7bj7qLHskVY4OoNaj9qu8TPdJ7kSAgUeRxWNngXlcNIGt4gexZGKVGcqZpqqWordXb_he1izY"},"authenticatorName":"iPhone Face-ID","challenge":"ArkQi2yAYHPlgnJNFBlneIwchQdWXBOTrdB-AmMUB21Lx","transports":["internal","hybrid"]}],"userId":"user_2m9F..."},"timestampMs":"1775681700000","type":"ACTIVITY_TYPE_CREATE_AUTHENTICATORS_V2"}' requestId: Request:7c4a8d09-ca37-4e3e-9e0d-8c2b3e9a1f21 expiresAt: '2026-04-08T15:35:00Z' + processingPending: + summary: Operation still processing (re-send the identical request) + value: + status: PENDING '400': description: >- Bad request. Returned with `EMAIL_OTP_CREDENTIAL_ALREADY_EXISTS` diff --git a/openapi/paths/auth/auth_credentials_{id}_challenge.yaml b/openapi/paths/auth/auth_credentials_{id}_challenge.yaml index 184d9cba9..fa8be2d14 100644 --- a/openapi/paths/auth/auth_credentials_{id}_challenge.yaml +++ b/openapi/paths/auth/auth_credentials_{id}_challenge.yaml @@ -107,6 +107,19 @@ post: challenge: 6b35a4c41d9aa7a2a0e742f9f9e7a1c2d65a2db33a3fb748f6d4f1ce78d9a729 requestId: Request:7c4a8d09-ca37-4e3e-9e0d-8c2b3e9a1f21 expiresAt: '2026-04-08T15:35:00Z' + '202': + description: >- + The operation is still processing. Grid ran it optimistically in line + but it has fallen back to asynchronous processing (for example, while a + new OTP is being issued or a passkey reauthentication challenge is being + prepared). No action beyond retrying is required: re-send the identical + request — same method, path, body, and headers — on a short interval + until it returns the terminal `200`. The response body carries + `status: PENDING` and nothing else to act on. + content: + application/json: + schema: + $ref: ../../components/schemas/common/ProcessingPendingResponse.yaml '400': description: Bad request content: diff --git a/openapi/paths/auth/auth_credentials_{id}_verify.yaml b/openapi/paths/auth/auth_credentials_{id}_verify.yaml index af9d90931..385a44882 100644 --- a/openapi/paths/auth/auth_credentials_{id}_verify.yaml +++ b/openapi/paths/auth/auth_credentials_{id}_verify.yaml @@ -144,18 +144,26 @@ post: $ref: ../../components/schemas/auth/AuthSession.yaml '202': description: >- - Verification challenge issued. Returned only for OTP credentials, - on the first leg of the secure OTP login flow. - Build an API-key stamp over `payloadToSign` (the - `verificationToken`) with the TEK keypair the client generated - for this login, then resubmit the same request with that full - stamp as `Grid-Wallet-Signature` and `requestId` echoed as - `Request-Id` to receive the issued session on the signed - retry. + Non-terminal response carrying one of two bodies, distinguished by + their fields. A signed-retry challenge (`payloadToSign` plus + `requestId`) is returned for OTP credentials on the first leg of the + secure OTP login flow: build an API-key stamp over `payloadToSign` (the + `verificationToken`) with the TEK keypair the client generated for this + login, then resubmit the same request with that full stamp as + `Grid-Wallet-Signature` and `requestId` echoed as `Request-Id` to + receive the issued session on the signed retry. + + + A still-processing body (`status: PENDING`) is returned when the + operation ran optimistically in line but has fallen back to + asynchronous processing — this can occur on the OTP signed retry or on + `OAUTH`/`PASSKEY` verification. Re-send the identical request, + unchanged, on a short interval until it returns the terminal `200`. Do + not add or alter a signature; the request is simply repeated as-is. content: application/json: schema: - $ref: ../../components/schemas/auth/AuthSignedRequestChallenge.yaml + $ref: ../../components/schemas/auth/AuthSignedRequestChallengeOrProcessingPending.yaml examples: emailOtp: summary: Email OTP verification challenge (sign and retry) @@ -164,6 +172,10 @@ post: payloadToSign: eyJhbGciOiJFUzI1NiIsImtpZCI6InR1cm5rZXkifQ.eyJzdWIiOiJUWnk2NkVPa1RGYTd2NkpXZ0VxaVgyZGFXOENXc2pMQzVDVU9aRUlGY3hzIiwiaWF0IjoxNzc5NDA3MjIxLCJleHAiOjE3Nzk0MTA4MjF9.gKX9MWYGkw8Y55bgzsgrRftvUHFruIe8yu0w9Kpjp5qnrZnXcTV71WVoltGPsr015IY_oRTOkIFLHmiGNG9zBw requestId: Request:7c4a8d09-ca37-4e3e-9e0d-8c2b3e9a1f21 expiresAt: '2026-04-08T15:35:00Z' + processingPending: + summary: Operation still processing (re-send the identical request) + value: + status: PENDING '400': description: Bad request content: diff --git a/openapi/paths/auth/auth_delegated-keys.yaml b/openapi/paths/auth/auth_delegated-keys.yaml index 5009d3de6..cc15a6436 100644 --- a/openapi/paths/auth/auth_delegated-keys.yaml +++ b/openapi/paths/auth/auth_delegated-keys.yaml @@ -110,12 +110,23 @@ post: updatedAt: '2026-04-08T15:30:42Z' '202': description: >- - Challenge issued for the next leg. Stamp `payloadToSign` and retry - the same request with `Grid-Wallet-Signature` and `Request-Id`. + Non-terminal response carrying one of two bodies, distinguished by + their fields. A signed-retry challenge (`payloadToSign` plus + `requestId`) is returned for the next leg of the flow: stamp + `payloadToSign` and retry the same request with `Grid-Wallet-Signature` + and `Request-Id`. + + + A still-processing body (`status: PENDING`) is returned when the + operation ran optimistically in line but has fallen back to + asynchronous processing — this can occur on either signed leg. Re-send + the identical request, unchanged, on a short interval until it returns + either the next signed-retry challenge or the terminal `201`. Do not + add or alter a signature; the request is simply repeated as-is. content: application/json: schema: - $ref: ../../components/schemas/auth/DelegatedKeySignedRequestChallenge.yaml + $ref: ../../components/schemas/auth/DelegatedKeySignedRequestChallengeOrProcessingPending.yaml '400': description: Bad request content: diff --git a/openapi/paths/auth/auth_delegated-keys_{id}.yaml b/openapi/paths/auth/auth_delegated-keys_{id}.yaml index 2b58efca4..f7ea4f48f 100644 --- a/openapi/paths/auth/auth_delegated-keys_{id}.yaml +++ b/openapi/paths/auth/auth_delegated-keys_{id}.yaml @@ -70,6 +70,17 @@ delete: type: string example: DelegatedKey:019542f5-b3e7-1d02-0000-000000000021 responses: + '202': + description: >- + The revocation is still processing. Grid ran it optimistically in line + but it has fallen back to asynchronous processing. Re-send the identical + `DELETE` request — same method, path, and headers — on a short interval + until it returns the terminal `204`. The response body carries + `status: PENDING` and nothing else to act on. + content: + application/json: + schema: + $ref: ../../components/schemas/common/ProcessingPendingResponse.yaml '204': description: >- Delegated key revoked. The key can no longer authorize signing. diff --git a/openapi/paths/auth/auth_sessions_{id}_refresh.yaml b/openapi/paths/auth/auth_sessions_{id}_refresh.yaml index 7248f7337..c30eb9990 100644 --- a/openapi/paths/auth/auth_sessions_{id}_refresh.yaml +++ b/openapi/paths/auth/auth_sessions_{id}_refresh.yaml @@ -88,13 +88,23 @@ post: expiresAt: '2026-04-08T15:50:00Z' '202': description: >- - Challenge issued. The response contains `payloadToSign` plus a - `requestId`. Build an API-key stamp over `payloadToSign` with the - current session API keypair, then echo `requestId` on the signed retry. + Non-terminal response carrying one of two bodies, distinguished by + their fields. A signed-retry challenge (`payloadToSign` plus + `requestId`) is returned on the initial call: build an API-key stamp + over `payloadToSign` with the current session API keypair, then echo + `requestId` on the signed retry. + + + A still-processing body (`status: PENDING`) is returned when the + operation ran optimistically in line but has fallen back to + asynchronous processing — this can occur on the signed retry. Re-send + the identical request, unchanged, on a short interval until it returns + the terminal `201`. Do not add or alter a signature; the request is + simply repeated as-is. content: application/json: schema: - $ref: ../../components/schemas/common/SignedRequestChallenge.yaml + $ref: ../../components/schemas/common/SignedRequestChallengeOrProcessingPending.yaml examples: challenge: summary: Session refresh challenge @@ -102,6 +112,10 @@ post: payloadToSign: '{"organizationId":"org_abc123","parameters":{"targetPublicKey":"04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2"},"timestampMs":"1746736509954","type":"ACTIVITY_TYPE_CREATE_READ_WRITE_SESSION_V2"}' requestId: Request:019542f5-b3e7-1d02-0000-000000000010 expiresAt: '2026-04-08T15:35:00Z' + processingPending: + summary: Operation still processing (re-send the identical request) + value: + status: PENDING '400': description: Bad request content: diff --git a/openapi/paths/customers/customers_{customerId}.yaml b/openapi/paths/customers/customers_{customerId}.yaml index 7f72bd663..bb8f86b0a 100644 --- a/openapi/paths/customers/customers_{customerId}.yaml +++ b/openapi/paths/customers/customers_{customerId}.yaml @@ -175,16 +175,25 @@ patch: $ref: ../../components/schemas/customers/CustomerOneOf.yaml '202': description: >- - Challenge issued for an Embedded Wallet email or SMS auth phone update. - The response contains `payloadToSign` plus a `requestId`. Build an - API-key stamp over `payloadToSign` with the session API keypair from a - verified authentication credential on one of the customer's tied - Embedded Wallets, then retry the same request with - `Grid-Wallet-Signature` and `Request-Id`. + Non-terminal response for an Embedded Wallet email or SMS auth phone + update, carrying one of two bodies distinguished by their fields. A + signed-retry challenge (`payloadToSign` plus `requestId`) is returned + on the initial call: build an API-key stamp over `payloadToSign` with + the session API keypair from a verified authentication credential on one + of the customer's tied Embedded Wallets, then retry the same request + with `Grid-Wallet-Signature` and `Request-Id`. + + + A still-processing body (`status: PENDING`) is returned when the + operation ran optimistically in line but has fallen back to + asynchronous processing — this can occur on the signed retry. Re-send + the identical request, unchanged, on a short interval until it returns + the terminal `200`. Do not add or alter a signature; the request is + simply repeated as-is. content: application/json: schema: - $ref: ../../components/schemas/common/SignedRequestChallenge.yaml + $ref: ../../components/schemas/common/SignedRequestChallengeOrProcessingPending.yaml examples: embeddedWalletEmailUpdate: summary: Embedded Wallet customer email update challenge @@ -198,6 +207,10 @@ patch: payloadToSign: '{"organizationId":"org_2m9F...","parameters":{"userId":"user_2m9F...","userPhoneNumber":"+14155559876"},"timestampMs":"1775681700000","type":"ACTIVITY_TYPE_UPDATE_USER_PHONE_NUMBER"}' requestId: Request:019542f5-b3e7-1d02-0000-000000000011 expiresAt: '2026-04-08T15:35:00Z' + processingPending: + summary: Operation still processing (re-send the identical request) + value: + status: PENDING '400': description: Bad request content: diff --git a/openapi/paths/internal_accounts/internal_accounts_{id}_export.yaml b/openapi/paths/internal_accounts/internal_accounts_{id}_export.yaml index a9769cbd0..7a2fc8e4a 100644 --- a/openapi/paths/internal_accounts/internal_accounts_{id}_export.yaml +++ b/openapi/paths/internal_accounts/internal_accounts_{id}_export.yaml @@ -89,14 +89,23 @@ post: $ref: ../../components/schemas/internal_accounts/InternalAccountExportResponse.yaml '202': description: >- - Challenge issued. The response contains `payloadToSign` (which - binds the submitted `clientPublicKey`) plus a `requestId`. - Build an API-key stamp over `payloadToSign` with the session - API keypair and echo `requestId` on the retry. + Non-terminal response carrying one of two bodies, distinguished by + their fields. A signed-retry challenge (`payloadToSign`, which binds + the submitted `clientPublicKey`, plus a `requestId`) is returned on the + initial call: build an API-key stamp over `payloadToSign` with the + session API keypair and echo `requestId` on the retry. + + + A still-processing body (`status: PENDING`) is returned when the + operation ran optimistically in line but has fallen back to + asynchronous processing — this can occur on the signed retry. Re-send + the identical request, unchanged (including the same `clientPublicKey`), + on a short interval until it returns the terminal `200`. Do not add or + alter a signature; the request is simply repeated as-is. content: application/json: schema: - $ref: ../../components/schemas/common/SignedRequestChallenge.yaml + $ref: ../../components/schemas/common/SignedRequestChallengeOrProcessingPending.yaml '400': description: Bad request content: