Cowdidocs
API ReferenceContact details

Confirm the email OTP

POST
/v1/user/settings/emails/{id}/otp/confirm

Confirms the OTP for the step named by step and validates the contact. A user token calls this on behalf of the signed-in user. When another OTP is still due, the email stays unvalidated and otp describes the next OTP. Returns 404 when the contact does not exist, and 409 when the email is already registered on another profile.

AuthorizationBearer <token>

Create a client with POST /v1/oauth/clients, then exchange its credentials for an access token. AUTHORIZATION_CODE clients act on behalf of a signed-in user and always use PKCE; CLIENT_CREDENTIALS clients act as themselves. A client may only be granted scopes its creator already holds — read the grantable list from GET /v1/oauth/clients/scopes.

In: header

Path Parameters

id*string

Unique identifier of the email contact.

Formatuuid

Request Body

application/json

The OTP code for the contact. step must echo otp.step from the contact response that this OTP answers.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/v1/user/settings/emails/550e8400-e29b-41d4-a716-446655440000/otp/confirm" \  -H "Content-Type: application/json" \  -d '{    "otp_code": "482913",    "step": "OWNER_AUTHORIZATION"  }'
{  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",  "value": "jane@example.com",  "otp": {    "step": "OWNER_AUTHORIZATION",    "sent_to": "EMAIL",    "steps": 2,    "digits": 6  },  "is_primary": true,  "validated": true,  "validated_at": "2026-01-15T09:20:00Z",  "requires_verification": true,  "verification_locked": true,  "verification_locked_at": "2026-01-20T16:45:00Z",  "created_at": "2026-09-01T10:15:30Z"}
{  "code": "BAD_REQUEST",  "description": "Bad Request"}
{  "code": "UNAUTHORISED",  "description": "Unauthorised"}
{  "code": "FORBIDDEN",  "description": "Forbidden"}
{  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",  "value": "jane@example.com",  "otp": {    "step": "OWNER_AUTHORIZATION",    "sent_to": "EMAIL",    "steps": 2,    "digits": 6  },  "is_primary": true,  "validated": true,  "validated_at": "2026-01-15T09:20:00Z",  "requires_verification": true,  "verification_locked": true,  "verification_locked_at": "2026-01-20T16:45:00Z",  "created_at": "2026-09-01T10:15:30Z"}
{  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",  "value": "jane@example.com",  "otp": {    "step": "OWNER_AUTHORIZATION",    "sent_to": "EMAIL",    "steps": 2,    "digits": 6  },  "is_primary": true,  "validated": true,  "validated_at": "2026-01-15T09:20:00Z",  "requires_verification": true,  "verification_locked": true,  "verification_locked_at": "2026-01-20T16:45:00Z",  "created_at": "2026-09-01T10:15:30Z"}
{  "code": "RATE_LIMIT_EXCEEDED",  "description": "Too Many Requests"}
{  "code": "INTERNAL_ERROR",  "description": "Internal Server Error"}