> ## Documentation Index
> Fetch the complete documentation index at: https://docs.shipfastai.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Users API: manage user profiles and accounts

> Reference for all Users API endpoints: get and update your profile, change password or email, export your data, and delete your account.

The Users API gives authenticated users full control over their own profile and account data. You can retrieve and update your profile, change credentials, request a GDPR-compliant data export, and permanently delete your account. All endpoints are mounted under `/api/users/` and require a valid Bearer token.

<Note>
  All endpoints on this page require an `Authorization: Bearer <access_token>` header. See [Authentication](/api-reference/authentication) for how to obtain a token.
</Note>

***

## GET /api/users/me

Return the full profile of the currently authenticated user.

```bash theme={null}
curl --request GET \
  --url http://localhost:8000/api/users/me \
  --header "Authorization: Bearer <access_token>"
```

**Response** — `UserResponse`:

<ResponseField name="id" type="string" required>
  UUID of the user.
</ResponseField>

<ResponseField name="email" type="string" required>
  The user's email address.
</ResponseField>

<ResponseField name="full_name" type="string">
  The user's display name.
</ResponseField>

<ResponseField name="avatar_url" type="string">
  URL to the user's profile picture.
</ResponseField>

<ResponseField name="is_active" type="boolean" required>
  Whether the account is active.
</ResponseField>

<ResponseField name="is_verified" type="boolean" required>
  Whether the email address has been verified.
</ResponseField>

<ResponseField name="oauth_provider" type="string">
  The OAuth provider used to create the account (`google`, `github`), or `null` for password-based accounts.
</ResponseField>

<ResponseField name="subscription_status" type="string" required>
  Current subscription status (e.g., `free`, `active`, `cancelled`).
</ResponseField>

<ResponseField name="subscription_tier" type="string" required>
  Current subscription tier (e.g., `free`, `pro`).
</ResponseField>

<ResponseField name="created_at" type="string" required>
  ISO 8601 timestamp of account creation.
</ResponseField>

```json theme={null}
{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "email": "user@example.com",
  "full_name": "Jane Smith",
  "avatar_url": "https://example.com/avatars/jane.png",
  "is_active": true,
  "is_verified": true,
  "oauth_provider": null,
  "subscription_status": "active",
  "subscription_tier": "pro",
  "created_at": "2024-01-15T10:30:00Z"
}
```

***

## PATCH /api/users/me

Update the authenticated user's profile. Only the fields you include in the request body are updated; omitted fields are left unchanged.

<ParamField body="full_name" type="string">
  A new display name for the user.
</ParamField>

<ParamField body="avatar_url" type="string">
  A new URL for the user's profile picture.
</ParamField>

<CodeGroup>
  ```bash curl theme={null}
  curl --request PATCH \
    --url http://localhost:8000/api/users/me \
    --header "Authorization: Bearer <access_token>" \
    --header "Content-Type: application/json" \
    --data '{
      "full_name": "Jane A. Smith",
      "avatar_url": "https://example.com/avatars/jane-new.png"
    }'
  ```

  ```python Python theme={null}
  import requests

  response = requests.patch(
      "http://localhost:8000/api/users/me",
      headers={"Authorization": f"Bearer {access_token}"},
      json={
          "full_name": "Jane A. Smith",
          "avatar_url": "https://example.com/avatars/jane-new.png",
      },
  )
  print(response.json())
  ```
</CodeGroup>

**Response** — `UserResponse` with updated fields:

```json theme={null}
{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "email": "user@example.com",
  "full_name": "Jane A. Smith",
  "avatar_url": "https://example.com/avatars/jane-new.png",
  "is_active": true,
  "is_verified": true,
  "oauth_provider": null,
  "subscription_status": "active",
  "subscription_tier": "pro",
  "created_at": "2024-01-15T10:30:00Z"
}
```

***

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

Change the password for the currently authenticated user. This endpoint is only available to accounts that were created with a password. OAuth-only accounts (social login only, no password set) must use the forgot-password flow to set an initial password.

<ParamField body="current_password" type="string" required>
  The user's existing password.
</ParamField>

<ParamField body="new_password" type="string" required>
  The new password to set.
</ParamField>

<CodeGroup>
  ```bash curl theme={null}
  curl --request POST \
    --url http://localhost:8000/api/users/me/change-password \
    --header "Authorization: Bearer <access_token>" \
    --header "Content-Type: application/json" \
    --data '{
      "current_password": "old-password-123",
      "new_password": "new-password-456"
    }'
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      "http://localhost:8000/api/users/me/change-password",
      headers={"Authorization": f"Bearer {access_token}"},
      json={
          "current_password": "old-password-123",
          "new_password": "new-password-456",
      },
  )
  print(response.json())
  ```
</CodeGroup>

**Response:**

```json theme={null}
{
  "message": "Password changed successfully"
}
```

Returns `400` if the current password is incorrect, or if the account uses social login and has no password set.

***

## POST /api/users/me/change-email

Request an email address change. The new address must not already be in use. After the change, `is_verified` is set to `false` and a new verification email is sent to the new address.

<ParamField body="new_email" type="string" required>
  The new email address to associate with the account. Must be a valid email format.
</ParamField>

<ParamField body="password" type="string" required>
  The user's current password to confirm the change. Required for password-based accounts.
</ParamField>

```bash theme={null}
curl --request POST \
  --url http://localhost:8000/api/users/me/change-email \
  --header "Authorization: Bearer <access_token>" \
  --header "Content-Type: application/json" \
  --data '{
    "new_email": "new-address@example.com",
    "password": "current-password-123"
  }'
```

**Response:**

```json theme={null}
{
  "message": "Verification email sent to your new address"
}
```

***

## GET /api/users/me/export

Export all personal data stored for the authenticated user as a downloadable JSON file. This endpoint is provided for GDPR compliance.

```bash theme={null}
curl --request GET \
  --url http://localhost:8000/api/users/me/export \
  --header "Authorization: Bearer <access_token>" \
  --output user-data-export.json
```

The response is a `Content-Disposition: attachment` JSON file with the following fields:

<ResponseField name="id" type="string">UUID of the user.</ResponseField>
<ResponseField name="email" type="string">Email address.</ResponseField>
<ResponseField name="full_name" type="string">Display name.</ResponseField>
<ResponseField name="avatar_url" type="string">Profile picture URL.</ResponseField>
<ResponseField name="oauth_provider" type="string">OAuth provider if applicable.</ResponseField>
<ResponseField name="is_verified" type="boolean">Email verification status.</ResponseField>
<ResponseField name="subscription_status" type="string">Current subscription status.</ResponseField>
<ResponseField name="subscription_tier" type="string">Current subscription tier.</ResponseField>
<ResponseField name="created_at" type="string">Account creation timestamp.</ResponseField>
<ResponseField name="updated_at" type="string">Last profile update timestamp.</ResponseField>
<ResponseField name="last_login_at" type="string">Most recent login timestamp.</ResponseField>
<ResponseField name="exported_at" type="string">Timestamp of when this export was generated.</ResponseField>

```json theme={null}
{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "email": "user@example.com",
  "full_name": "Jane Smith",
  "avatar_url": null,
  "oauth_provider": null,
  "is_verified": true,
  "subscription_status": "active",
  "subscription_tier": "pro",
  "created_at": "2024-01-15T10:30:00.000000",
  "updated_at": "2024-03-01T14:22:00.000000",
  "last_login_at": "2024-03-10T09:00:00.000000",
  "exported_at": "2024-03-10T09:05:00.000000"
}
```

***

## DELETE /api/users/me

Permanently delete the authenticated user's account. This action is irreversible.

For **password-based accounts**, you must supply the current password to confirm deletion.

For **OAuth-only accounts** (no password), you must pass `"confirm": "DELETE"` instead.

<ParamField body="password" type="string">
  The user's current password. Required for password-based accounts.
</ParamField>

<ParamField body="confirm" type="string">
  Must be the exact string `"DELETE"`. Required for OAuth-only accounts that have no password.
</ParamField>

<Warning>
  Deleting an account is permanent. All user data is removed from the database immediately and cannot be recovered.
</Warning>

<CodeGroup>
  ```bash Password account theme={null}
  curl --request DELETE \
    --url http://localhost:8000/api/users/me \
    --header "Authorization: Bearer <access_token>" \
    --header "Content-Type: application/json" \
    --data '{"password": "current-password-123"}'
  ```

  ```bash OAuth account theme={null}
  curl --request DELETE \
    --url http://localhost:8000/api/users/me \
    --header "Authorization: Bearer <access_token>" \
    --header "Content-Type: application/json" \
    --data '{"confirm": "DELETE"}'
  ```
</CodeGroup>

**Response:**

```json theme={null}
{
  "message": "User deleted successfully"
}
```
