Cowdidocs
API ReferenceContact details

Send the primary phone OTP

POST
/v1/user/settings/phones/primary/otp/send

Sends or resends the owner-authorization or new-number OTP for the caller's primary-phone-number change. The otp of the response tells where it went. A user token calls this on behalf of the signed-in user. Returns 404 when the phone number is not a contact on the caller's profile, and 409 when the current-account state changed and the flow must restart.

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

Request Body

application/json

The validated phone number to make the caller's primary phone number. When authorization_channel is omitted, the owner-authorization OTP goes to the caller's current primary contact of the target type.

Response Body

application/json

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/phones/primary/otp/send" \  -H "Content-Type: application/json" \  -d '{    "phone_number": "+254712345678"  }'
{  "status": "OTP_REQUIRED",  "contact": {    "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"  },  "otp": {    "step": "OWNER_AUTHORIZATION",    "sent_to": "EMAIL",    "steps": 2,    "digits": 6  },  "otp_url": "/v1/user/settings/emails/primary/otp/send",  "confirm_url": "/v1/user/settings/emails/primary/otp/confirm",  "status_url": "/v1/user/settings/emails/primary/change",  "identity_sync_pending": true}
{  "status": "OTP_REQUIRED",  "contact": {    "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"  },  "otp": {    "step": "OWNER_AUTHORIZATION",    "sent_to": "EMAIL",    "steps": 2,    "digits": 6  },  "otp_url": "/v1/user/settings/emails/primary/otp/send",  "confirm_url": "/v1/user/settings/emails/primary/otp/confirm",  "status_url": "/v1/user/settings/emails/primary/change",  "identity_sync_pending": true}
{  "code": "BAD_REQUEST",  "description": "Bad Request"}
{  "code": "UNAUTHORISED",  "description": "Unauthorised"}
{  "code": "FORBIDDEN",  "description": "Forbidden"}
{  "status": "OTP_REQUIRED",  "contact": {    "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"  },  "otp": {    "step": "OWNER_AUTHORIZATION",    "sent_to": "EMAIL",    "steps": 2,    "digits": 6  },  "otp_url": "/v1/user/settings/emails/primary/otp/send",  "confirm_url": "/v1/user/settings/emails/primary/otp/confirm",  "status_url": "/v1/user/settings/emails/primary/change",  "identity_sync_pending": true}
{  "status": "OTP_REQUIRED",  "contact": {    "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"  },  "otp": {    "step": "OWNER_AUTHORIZATION",    "sent_to": "EMAIL",    "steps": 2,    "digits": 6  },  "otp_url": "/v1/user/settings/emails/primary/otp/send",  "confirm_url": "/v1/user/settings/emails/primary/otp/confirm",  "status_url": "/v1/user/settings/emails/primary/change",  "identity_sync_pending": true}
{  "code": "RATE_LIMIT_EXCEEDED",  "description": "Too Many Requests"}
{  "code": "INTERNAL_ERROR",  "description": "Internal Server Error"}