Authentication

Login, logout, session cookies, and profile management. AuthWorx uses short-lived JWTs stored in httpOnly cookies — the browser never exposes them to JavaScript.

Base URL https://authworx.uthings.io/api/v1
ℹ️
Include X-Org-Slug: your-org-slug on every request. This scopes the operation to the correct organization.

Login

Authenticate a user with email and password. Returns access and refresh tokens. If the user has two-factor authentication enabled, a partial token is set instead — see Two-Factor Auth.

POST /auth/login

Request body

FieldTypeDescription
emailstringrequiredUser's email address.
passwordstringrequiredUser's password.
Request
curl -X POST https://authworx.uthings.io/api/v1/auth/login \
  -H "X-Org-Slug: acme-corp" \
  -H "Content-Type: application/json" \
  -d '{ "email": "alice@acme.com", "password": "correct-horse" }'
Response — success (200)
{
  "status": "success",
  "data": {
    "accessToken": "eyJhbGciOiJIUzI1NiIs...",
    "refreshToken": "eyJhbGciOiJIUzI1NiIs...",
    "user": {
      "id": "usr_01HXYZ",
      "name": "Alice Chen",
      "email": "alice@acme.com",
      "role": "user",
      "isEmailVerified": true
    },
    "membership": {
      "role": "member",
      "status": "active"
    }
  }
}
Response — 2FA required (200)
{
  "status": "success",
  "data": {
    "requires2FA": true
  }
}

When requires2FA is true, a short-lived partial_token cookie is set. Exchange it for a full session via POST /auth/verify-2fa.

Error responses

StatusCause
401Invalid email or password.
403User is not a member of this organization, or membership is not active.
429Too many failed attempts. Back off and retry after the indicated delay.

Logout

Invalidates the current session and clears all auth cookies.

POST /auth/logout

No request body required. The server clears access_token, refresh_token, and partial_token cookies.

Response (200)
{ "status": "success", "data": { "message": "Logged out successfully" } }

Get profile

Returns the currently authenticated user's profile.

GET /auth/profile

Headers

HeaderDescription
Cookie: access_tokenrequiredActive session token set by login.
Response (200)
{
  "status": "success",
  "data": {
    "user": {
      "id": "usr_01HXYZ",
      "name": "Alice Chen",
      "email": "alice@acme.com",
      "role": "user",
      "isEmailVerified": true,
      "profile": {
        "bio": "Product designer at Acme.",
        "phone": "+1 555 000 0000"
      }
    }
  }
}

Update profile

Updates the display name and optional profile fields.

PUT /auth/profile

Request body

FieldTypeDescription
namestringrequiredDisplay name (1–100 characters).
biostringoptionalShort bio.
phonestringoptionalPhone number.
Request
{ "name": "Alice Chen", "bio": "Product designer.", "phone": "+1 555 000 0000" }
Response (200)
{
  "status": "success",
  "data": {
    "user": { "id": "usr_01HXYZ", "name": "Alice Chen", "email": "alice@acme.com", "profile": { "bio": "Product designer.", "phone": "+1 555 000 0000" } }
  }
}

Change password

POST /auth/change-password

Request body

FieldTypeDescription
currentPasswordstringrequiredThe user's existing password.
newPasswordstringrequiredNew password — minimum 8 characters.
Response (200)
{ "status": "success", "data": { "message": "Password updated successfully" } }

Error responses

StatusCause
400New password is too short or does not meet complexity requirements.
401currentPassword is incorrect.

💡
For token refresh, see Tokens — POST /auth/refresh.