v5

latestOpenAPI 3.1.0Proprietary2026-08-011476181.4 MB
Embedded Wallet Auth

Verify an authentication credential

Complete 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. For OAUTH and PASSKEY the session signing key is delivered as encryptedSessionSigningKey (HPKE-sealed to the supplied clientPublicKey); for OTP credentials the client already holds the session signing key (the TEK private key it generated) and that field is omitted from the response. The expiresAt timestamp marks when the session expires.

post/auth/credentials/{id}/verify

Path parameters

idstring required

The id of the authentication credential to verify (the id field of the AuthMethod returned from POST /auth/credentials).

Headers

Grid-Wallet-Signaturestring

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.

Request-Idstring

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

OR
OR
OR

Example request

{
  "encryptedOtpBundle": "{\"encappedPublic\":\"044f631a2d890bc6668d997ee184e190650d06adf970987568ec641214a00403b73effe1ef406c60a5cde8508a4484567ddb8056fbd493bee614cd727aef02a838\",\"ciphertext\":\"1fa1023390a56539aa48cbb380aa28f544ed5cc04861566bb806e25ba026f14660eaf4140a05b388dd012eaa899759a6a92576cdca8c1b7d12e147bd96cc26ed9f74886794155d8ac5cf0fdc\"}"
}

Response

Authentication credential verified and session issued

idstring required

System-generated unique identifier for the session. Pass this value to DELETE /auth/sessions/{id} to revoke the session before expiresAt. Overrides the id inherited from AuthMethod so this response identifies the session rather than the authenticating credential.

accountIdstring required

Identifier of the internal account that this credential authenticates.

type'OAUTH' | 'EMAIL_OTP' | 'SMS_OTP' | 'PASSKEY' required

The type of authentication credential.

  • OAUTH: OpenID Connect (OIDC) token issued by an identity provider such as Google or Apple.
  • EMAIL_OTP: A one-time password delivered to the user's email address.
  • SMS_OTP: A one-time password delivered to the user's phone number.
  • PASSKEY: A WebAuthn passkey bound to the user's device.
credentialIdstring

Base64url-encoded WebAuthn credential identifier for this passkey. Present only for PASSKEY authentication credentials. Corresponds to PublicKeyCredential.rawId; pass this value as allowCredentials[].id when requesting a passkey assertion for this auth method.

nicknamestring required

Human-readable identifier for this credential. For EMAIL_OTP credentials this is the email address; for SMS_OTP credentials this is the E.164 phone number; for OAUTH credentials it is typically the email claim from the OIDC token; for PASSKEY credentials it is the validated nickname provided at registration time.

createdAtstring date-time required

Creation timestamp.

updatedAtstring date-time required

Last update timestamp.

encryptedSessionSigningKeystring

HPKE-encrypted session signing key, sealed to the clientPublicKey supplied on the verification or refresh request. Encoded as a base58check string: the decoded payload is a 33-byte compressed P-256 encapsulated public key followed by AES-256-GCM ciphertext. The client decrypts this key with its private key and uses it to sign subsequent Embedded Wallet requests until expiresAt.

Returned only by session-issuing responses for OAUTH and PASSKEY credentials. EMAIL_OTP and SMS_OTP sessions omit this field — the client generates a TEK keypair before verification and retains the private key throughout, so the server has nothing to deliver. Always omitted from list responses (GET /auth/sessions) since Grid does not retain the plaintext key after the client has decrypted it.

expiresAtstring date-time required

Timestamp after which the session is no longer valid and the encryptedSessionSigningKey must not be used to sign further requests.

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"
}