Verify an authentication credential
Changed onComplete the verification step for a previously created authentication credential and issue a session.
For EMAIL_OTP and SMS_OTP credentials, submit the encryptedOtpBundle produced by HPKE-encrypting {otp_code, public_key} under the otpEncryptionTargetBundle returned from registration when present, or from POST /auth/credentials/{id}/challenge when registration omitted it or the OTP must be reissued. The server is a pass-through and never sees the plaintext OTP code. On success the response is 202 with a payloadToSign carrying the verificationToken bound to the client's TEK public key — sign that token with the matching TEK private key, then retry the same request with the full stamp in Grid-Wallet-Signature and the requestId echoed in Request-Id. The signed retry returns 200 with the issued AuthSession. The TEK public key becomes the session API key on successful completion. In sandbox mode, the OTP flow runs real HPKE end-to-end against a sandbox enclave keypair — clients build a real encryptedOtpBundle against the sandbox otpEncryptionTargetBundle and sign a real verificationToken with their TEK keypair. The only sandbox shortcut is the magic OTP code ("000000") the user "receives" instead of a real email or SMS delivery.
For OAUTH credentials, supply a fresh OIDC token (iat must be less than 60 seconds before the request) along with the client-generated public key; this is also the reauthentication path after a prior session expired. The token identity (iss, aud, and sub) must match the OAuth credential being verified. In sandbox, the token's nonce must equal sha256(clientPublicKey). For PASSKEY credentials, the client completes a WebAuthn assertion (navigator.credentials.get()) against the Grid-issued challenge returned from POST /auth/credentials/{id}/challenge, and submits the resulting assertion with the Request-Id header. The clientPublicKey for PASSKEY credentials is supplied on the challenge call, where it is bound into the pending session-creation request.
On success for OAUTH and PASSKEY, and on the signed retry for OTP credentials, the response contains an AuthSession. Sending a compressed clientPublicKey selects the recommended client-held-key model: the client already holds the session signing key — the private key it generated before authentication — so no key material is returned and the deprecated encryptedSessionSigningKey is omitted. Sending an uncompressed clientPublicKey selects the deprecated legacy flow, where the session signing key is HPKE-sealed to that key and returned as encryptedSessionSigningKey for the client to decrypt. The expiresAt timestamp marks when the session expires.
Request
- Base URL: https://api.lightspark.com/grid/2025-10-13
- URL: https://api.lightspark.com/grid/2025-10-13/auth/credentials/{id}/verify
- Auth: HTTP basic
Path parameters
The id of the authentication credential to verify (the id field of the AuthMethod returned from POST /auth/credentials).
Headers
Full API-key stamp built over the prior payloadToSign with the TEK (Target Encryption Key) keypair the client generated for this login. Required on the signed retry that completes an EMAIL_OTP or SMS_OTP verification. Not used by OAUTH or PASSKEY verification, which complete in a single call.
The requestId returned in a prior 202 response from this endpoint, echoed back exactly here so the server can correlate the signed retry with the issued challenge. Required on the signed retry that completes an EMAIL_OTP or SMS_OTP verification; must be paired with Grid-Wallet-Signature. For PASSKEY verification, the requestId issued from POST /auth/credentials/{id}/challenge is echoed here instead so the server can correlate the assertion with the pending challenge.
Request body
Example request
{
"encryptedOtpBundle": "{\"encappedPublic\":\"044f631a2d890bc6668d997ee184e190650d06adf970987568ec641214a00403b73effe1ef406c60a5cde8508a4484567ddb8056fbd493bee614cd727aef02a838\",\"ciphertext\":\"1fa1023390a56539aa48cbb380aa28f544ed5cc04861566bb806e25ba026f14660eaf4140a05b388dd012eaa899759a6a92576cdca8c1b7d12e147bd96cc26ed9f74886794155d8ac5cf0fdc\"}"
}Response
Authentication credential verified and session issued (AuthSession); or, when the underlying wallet-provider activity is still in flight, a WalletOperationProcessing body with status: "PROCESSING" — the client re-sends the byte-identical request until it gets the session, and the backend also reconciles the activity to terminal on its own.
Example response
{
"id": "Session:019542f5-b3e7-1d02-0000-000000000003",
"accountId": "InternalAccount:019542f5-b3e7-1d02-0000-000000000002",
"credentialId": "KEbWNCc7NgaYnUyrNeFGX9_3Y-8oJ3KwzjnaiD1d1LVTxR7v3CaKfCz2Vy_g_MHSh7yJ8yL0Pxg6jo_o0hYiew",
"nickname": "example@lightspark.com",
"createdAt": "2026-04-08T15:30:01Z",
"updatedAt": "2026-04-08T15:35:00Z",
"encryptedSessionSigningKey": "w99a5xV6A75TfoAUkZn869fVyDYvgVsKrawMALZXmrauZd8hEv66EkPU1Z42CUaHESQjcA5bqd8dynTGBMLWB9ewtXWPEVbZvocB4Tw2K1vQVp7uwjf",
"expiresAt": "2026-04-09T15:30:01Z"
}Changes
- breaking
removed the required property
from the response with the status - breaking
removed the required property
from the response with the status - breaking
removed the required property
from the response with the status - breaking
removed the required property
from the response with the status - breaking
removed the required property
from the response with the status - breaking
removed the required property
from the response with the status - breaking
removed the required property
from the response with the status - breaking
removed the required property
from the response with the status - breaking
removed the required property
from the response with the status - breaking
removed the required property
from the response with the status - warning
added the new
ACCOUNT_NOT_FOUNDenum value to theresponse property for the response status - warning
added the new
AUTH_METHOD_NOT_FOUNDenum value to theresponse property for the response status - warning
added the new
CUSTOMER_NOT_FOUNDenum value to theresponse property for the response status - warning
added the new
DOCUMENT_HOLDER_NOT_FOUNDenum value to theresponse property for the response status - warning
added the new
INSUFFICIENT_FUNDSenum value to theresponse property for the response status - warning
added the new
NOT_FOUNDenum value to theresponse property for the response status - warning
added the new
PAYMENT_URL_NOT_FOUNDenum value to theresponse property for the response status - warning
added the new
PLATFORM_NOT_FOUNDenum value to theresponse property for the response status - warning
added the new
QUOTE_EXPIREDenum value to theresponse property for the response status - warning
added the new
QUOTE_RATE_UNAVAILABLEenum value to theresponse property for the response status - warning
added the new
REQUEST_NOT_FOUNDenum value to theresponse property for the response status - warning
added the new
SESSION_NOT_FOUNDenum value to theresponse property for the response status - warning
added the new
STABLECOIN_AMOUNT_NOT_REPRESENTABLEenum value to theresponse property for the response status - warning
added the new
STABLECOIN_BURN_SOURCE_NOT_SUPPORTEDenum value to theresponse property for the response status - warning
added the new
STABLECOIN_EXTERNAL_ACCOUNT_LINK_FAILEDenum value to theresponse property for the response status - warning
added the new
STABLECOIN_EXTERNAL_ACCOUNT_LINK_METHOD_REQUIREDenum value to theresponse property for the response status - warning
added the new
STABLECOIN_EXTERNAL_ACCOUNT_NOT_FOUNDenum value to theresponse property for the response status - warning
added the new
STABLECOIN_EXTERNAL_ACCOUNT_NOT_LINKEDenum value to theresponse property for the response status - warning
added the new
STABLECOIN_EXTERNAL_ACCOUNT_NOT_SUPPORTEDenum value to theresponse property for the response status - warning
added the new
STABLECOIN_EXTERNAL_ACCOUNT_PROVIDER_LINK_FAILEDenum value to theresponse property for the response status - warning
added the new
STABLECOIN_EXTERNAL_ACCOUNT_PROVIDER_LINK_REQUIREDenum value to theresponse property for the response status - warning
added the new
STABLECOIN_GRID_OPERATIONS_NOT_ENABLEDenum value to theresponse property for the response status - warning
added the new
STABLECOIN_NOT_FOUNDenum value to theresponse property for the response status - warning
added the new
STABLECOIN_NOT_PROVISIONEDenum value to theresponse property for the response status - warning
added the new
STABLECOIN_OPERATION_NOT_FOUNDenum value to theresponse property for the response status - warning
added the new
STABLECOIN_OPERATION_NOT_SUPPORTEDenum value to theresponse property for the response status - warning
added the new
STABLECOIN_PROVIDER_ERRORenum value to theresponse property for the response status - warning
added the new
STABLECOIN_PROVIDER_SOURCE_NOT_LINKEDenum value to theresponse property for the response status - warning
added the new
STABLECOIN_VERIFICATION_FAILEDenum value to theresponse property for the response status - warning
added the new
VERIFICATION_NOT_FOUNDenum value to theresponse property for the response status - info
added the required property
to the response with the status - info
added the required property
to the response with the status - info
added the required property
to the response with the status - info
added the required property
to the response with the status - info
added the required property
to the response with the status
- breaking
- info
removed
subschema #2from the response bodyallOflist for the response status - info
added to the response body
anyOflist for the response status
- info