Users

The users API lets you manage the authenticated user’s profile, password, profile image, and identities (email and phone). All endpoints operate on the currently authenticated user via /users/me.

Endpoints

Method Endpoint Description
GET /users/me Get current user profile
PATCH /users/me Update current user profile
POST /users/me/change-password Change password
POST /users/me/profile-image Upload profile image
DELETE /users/me/profile-image Remove profile image
GET /users/me/identities List identities
POST /users/me/identities Add an identity
DELETE /users/me/identities Remove an identity
POST /users/me/identities/verify Request identity verification

Get Current User

GET /api/v2/users/me

Returns the authenticated user’s profile, including their identities.

Response

{
  "id": 7,
  "created_at": "2024-01-15T08:30:00Z",
  "first_name": "Ola",
  "last_name": "Nordmann",
  "profile_image_url": "https://cdn.snapbooks.no/profile-images/abc123.jpg",
  "last_login": "2026-03-31T14:22:00Z",
  "identities": [
    {
      "type": "email",
      "value": "ola@example.com",
      "verified": true
    },
    {
      "type": "phone",
      "value": "+4791234567",
      "verified": false
    }
  ]
}

Update Current User

PATCH /api/v2/users/me

Updates the authenticated user’s first name and/or last name.

Request Body

Field Type Required Description
first_name string No User’s first name
last_name string No User’s last name

Example Request

{
  "first_name": "Ola",
  "last_name": "Nordmann"
}

Response

Returns the updated user object (same shape as GET /users/me).


Change Password

POST /api/v2/users/me/change-password

Changes the authenticated user’s password. Rate limited to 5 requests per hour.

Request Body

Field Type Required Description
password string Yes Current password
new_password string Yes New password

Password Requirements

  • Minimum 8 characters
  • Must contain at least one uppercase letter
  • Must contain at least one lowercase letter
  • Must contain at least one number
  • Must be different from the current password

Example Request

{
  "password": "OldPass123",
  "new_password": "NewSecure456"
}

Response

{
  "message": "Password changed successfully"
}

Error Responses

Status Code Description
400 common.validation_error Missing request body, password, or new_password
400 user.password_unchanged The new password is identical to the current one
400 user.weak_password The new password does not meet the requirements above
401 user.invalid_current_password The supplied current password is incorrect
429 — Rate limit exceeded (5 per hour)

Upload Profile Image

POST /api/v2/users/me/profile-image

Uploads a new profile image for the authenticated user. The request must use multipart/form-data encoding.

Request Body

Field Type Required Description
file file Yes Image file (JPEG, PNG, or WebP)

Allowed Content Types

  • image/jpeg
  • image/jpg
  • image/png
  • image/webp

Response

Returns the updated user object with the new profile_image_url.

Error Responses

Status Code Description
400 common.validation_error No file part in the request, or no file selected
400 user.unsupported_image_type The Content-Type is not JPEG, PNG, or WebP
400 user.invalid_image_content The file contents are not a valid image of the declared type

Remove Profile Image

DELETE /api/v2/users/me/profile-image

Removes the authenticated user’s profile image.

Response

Returns the updated user object with profile_image_url set to null.


List Identities

GET /api/v2/users/me/identities

Returns the authenticated user’s identities (email and phone number).

Response

Returns the user object with the identities array populated. See the response example in Get Current User.


Add an Identity

POST /api/v2/users/me/identities

Adds a phone number identity to the authenticated user. Email changes are not supported through this endpoint.

Request Body

Field Type Required Description
type string Yes Identity type. Only phone is supported
value string Yes The phone number

Example Request

{
  "type": "phone",
  "value": "+4791234567"
}

Response

Returns the updated user object with identities.

Error Responses

Status Code Description
400 common.validation_error Missing request body, type, or value
400 user.email_identity_immutable type was email — email changes are not supported here
400 user.unsupported_identity_type type is neither phone nor email

Remove an Identity

DELETE /api/v2/users/me/identities

Removes a phone number identity from the authenticated user. Email cannot be removed.

Request Body

Field Type Required Description
type string Yes Identity type to remove. Only phone is supported

Example Request

{
  "type": "phone"
}

Response

Returns the updated user object with identities.

Error Responses

Status Code Description
400 common.validation_error Missing request body or type
400 user.email_identity_immutable type was email — the email identity cannot be removed
400 user.unsupported_identity_type type is neither phone nor email

Request Identity Verification

POST /api/v2/users/me/identities/verify

Sends a verification email to the authenticated user. Rate limited to 5 requests per hour. Only email verification is currently supported.

Request Body

Field Type Required Description
type string Yes Identity type to verify. Only email is supported
value string Yes The email address to verify (must match the stored email)

Example Request

{
  "type": "email",
  "value": "ola@example.com"
}

Response

{
  "message": "Verification email sent"
}

Error Responses

Status Code Description
400 common.validation_error Missing request body, type, or value
400 user.unsupported_identity_type type is not email
400 user.identity_value_mismatch value does not match the stored email address
400 user.identity_already_verified The email address is already verified
429 — Rate limit exceeded (5 per hour)

Attributes

Attribute Type Description
id integer Unique identifier (read-only)
created_at datetime Account creation timestamp (read-only)
first_name string User’s first name
last_name string User’s last name
profile_image_url string URL to the user’s profile image (read-only)
last_login datetime Last login timestamp (read-only)

Identity

Attribute Type Description
type string Identity type: email or phone
value string The identity value (email address or phone number)
verified boolean Whether the identity has been verified. Only email verification is supported; phone identities always return false

Error Codes

Errors use the standard error envelope. Branch on code, not on message. In addition to the common codes, the /users/me endpoints return:

Code HTTP status When
user.password_unchanged 400 The new password equals the current password
user.weak_password 400 The new password is shorter than 8 characters or lacks an uppercase letter, a lowercase letter, or a number
user.invalid_current_password 401 The password field does not match the stored password
user.unsupported_image_type 400 The uploaded profile image is not JPEG, PNG, or WebP
user.invalid_image_content 400 The uploaded file’s contents are not a valid image
user.email_identity_immutable 400 An attempt to add, change, or remove the email identity
user.unsupported_identity_type 400 An identity type other than the one the endpoint supports
user.identity_value_mismatch 400 The value sent to the verify endpoint is not the user’s stored email
user.identity_already_verified 400 The email address has already been verified

Example Error Response

{
    "error": {
        "code": "user.weak_password",
        "message": "Password must be at least 8 characters with uppercase, lowercase, and a number",
        "request_id": "a1b2c3d4-5678-90ab-cdef-1234567890ab"
    }
}