Cowdidocs

Merge a duplicate user into a user

POST
/v1/users/{userId}/merge

Merge a duplicate user that has only a WorkOS login into the user in the path. The user in the path gets the WorkOS login, the verified email, and the organization memberships. The duplicate user becomes inactive and keeps its history. Requires the org:users:write permission on the cowdi organization. Returns 200 with no change when the merge already happened. Returns 409 when the duplicate user has a phone sign-in, an open account, or an active merchant membership. Returns 409 when the user in the path already has a WorkOS login or an email, or when either user is merged into another user.

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

userId*string

Unique identifier of the user that keeps the identity.

Formatuuid

Request Body

application/json

Request to merge a duplicate user into the user in the path.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/v1/users/550e8400-e29b-41d4-a716-446655440000/merge" \  -H "Content-Type: application/json" \  -d '{    "duplicate_user_id": "550e8400-e29b-41d4-a716-446655440000"  }'
{  "id": "b50e8400-e29b-41d4-a716-446655440000",  "auth_id": "sadoj21su9b23b19gvgb",  "first_name": "John",  "last_name": "Doe",  "status": "ACTIVE",  "email": "john.doe@example.com",  "email_verified": true,  "phone_number": "+254712345678",  "tag": "@johnd1234",  "locale": "en-KE",  "timezone": "Africa/Nairobi",  "last_login_at": "2026-02-03T10:15:30Z",  "organization": "cowdi",  "external_user_id": "GW-12345",  "is_test": false,  "source": "ADMIN_API",  "suspension": {    "at": "2026-03-10T08:00:00Z",    "reason": "FRAUD",    "internal_note": "string",    "external_message": "string"  },  "avatar_options": "seed=k3f9x2&skinColor=edb98a",  "resource_id": "string"}
{  "code": "BAD_REQUEST",  "description": "Bad Request"}
{  "code": "UNAUTHORISED",  "description": "Unauthorised"}
{  "code": "FORBIDDEN",  "description": "Forbidden"}
{  "code": "BAD_REQUEST",  "description": "Invalid input"}
{  "code": "RATE_LIMIT_EXCEEDED",  "description": "Too Many Requests"}
{  "code": "INTERNAL_ERROR",  "description": "Internal Server Error"}