curl --request POST \
--url https://api.lightspark.com/grid/2025-10-13/auth/credentials \
--header 'Authorization: Basic <encoded-value>' \
--header 'Content-Type: application/json' \
--data '
{
"type": "EMAIL_OTP",
"accountId": "InternalAccount:019542f5-b3e7-1d02-0000-000000000002"
}
'{
"id": "AuthMethod:019542f5-b3e7-1d02-0000-000000000001",
"accountId": "InternalAccount:019542f5-b3e7-1d02-0000-000000000002",
"type": "EMAIL_OTP",
"nickname": "example@lightspark.com",
"createdAt": "2026-04-08T15:30:01Z",
"updatedAt": "2026-04-08T15:30:01Z"
}Register an authentication credential for an Embedded Wallet customer.
First credential on an internal account
If the target internal account does not yet have any authentication credential registered, call this endpoint with the credential details. The response is 201 with the created AuthMethod. For EMAIL_OTP credentials, this call also triggers a one-time password email to the address on the customer record tied to the internal account; the credential must be activated via POST /auth/credentials/{id}/verify before it can sign requests. For OAUTH credentials, the supplied oidcToken is validated inline against the issuer’s .well-known OpenID configuration (the token’s iat must be less than 60 seconds before the request); activation still happens via POST /auth/credentials/{id}/verify. For PASSKEY credentials, the client completes a WebAuthn registration (navigator.credentials.create()) using a challenge issued by the platform backend and submits the resulting attestation here. The registration response is a plain AuthMethod (no inline authentication challenge). To produce the first session, the client follows registration with two further calls: POST /auth/credentials/{id}/challenge (carrying the client’s ephemeral clientPublicKey) returns a Grid-issued WebAuthn challenge plus requestId, and POST /auth/credentials/{id}/verify (with Request-Id: <requestId>) consumes the resulting assertion and issues the session. The same two-step pattern is used on every subsequent reauthentication. Only one PASSKEY credential is supported per internal account in v1.
Adding an additional credential
Registering an additional credential against an internal account that already has one requires a signature from an existing verified credential. Call this endpoint with the new credential’s details; if an existing credential is already registered on the internal account the response is 202 with a payloadToSign and a requestId. Use the session API keypair of an existing verified credential on the same internal account (decrypted client-side from its encryptedSessionSigningKey) to build an API-key stamp over payloadToSign, then retry the same request with that full stamp as the Grid-Wallet-Signature header and the requestId echoed back as the Request-Id header. The signed retry returns 201 with the created AuthMethod. For EMAIL_OTP, the OTP email is triggered on the signed retry, and the credential must then be activated via POST /auth/credentials/{id}/verify.
curl --request POST \
--url https://api.lightspark.com/grid/2025-10-13/auth/credentials \
--header 'Authorization: Basic <encoded-value>' \
--header 'Content-Type: application/json' \
--data '
{
"type": "EMAIL_OTP",
"accountId": "InternalAccount:019542f5-b3e7-1d02-0000-000000000002"
}
'{
"id": "AuthMethod:019542f5-b3e7-1d02-0000-000000000001",
"accountId": "InternalAccount:019542f5-b3e7-1d02-0000-000000000002",
"type": "EMAIL_OTP",
"nickname": "example@lightspark.com",
"createdAt": "2026-04-08T15:30:01Z",
"updatedAt": "2026-04-08T15:30:01Z"
}API token authentication using format <api token id>:<api client secret>
Full API-key stamp built over the prior payloadToSign with the session API keypair of an existing verified authentication credential on the target internal account. Required when registering an additional credential on an internal account that already has one; ignored when the internal account has no existing credentials.
The requestId returned in a prior 202 response, echoed back on the signed retry so the server can correlate it with the issued challenge. Required on the signed retry when registering an additional credential; must be paired with Grid-Wallet-Signature.
Authentication credential created successfully. The body is the created AuthMethod for all three credential types. For PASSKEY, the credential must be authenticated for the first time via POST /auth/credentials/{id}/challenge followed by POST /auth/credentials/{id}/verify to produce a session — there is no inline authentication challenge on the registration response.
Strict wrapper around AuthMethod. Used directly as the registration response on POST /auth/credentials (all three credential types) and inside AuthCredentialResponseOneOf for the EMAIL_OTP and OAUTH branches of POST /auth/credentials/{id}/challenge. The only difference from AuthMethod is unevaluatedProperties: false, which disambiguates the oneOf against PasskeyAuthChallenge — without the strictness, an AuthMethod with extra fields would ambiguously match both branches.
System-generated unique identifier for the authentication credential.
"AuthMethod:019542f5-b3e7-1d02-0000-000000000001"
Identifier of the internal account that this credential authenticates.
"InternalAccount:019542f5-b3e7-1d02-0000-000000000002"
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.PASSKEY: A WebAuthn passkey bound to the user's device.OAUTH, EMAIL_OTP, PASSKEY Human-readable identifier for this credential. For EMAIL_OTP credentials this is the email address; for OAUTH credentials it is typically the email claim from the OIDC token; for PASSKEY credentials it is the nickname provided at registration time.
"example@lightspark.com"
Creation timestamp.
"2026-04-08T15:30:01Z"
Last update timestamp.
"2026-04-08T15:35:00Z"
Was this page helpful?