Skip to content

Authentication API

Endpoints for user registration, login, OAuth, device code flow, session management, and SSO.

Register

Create a new account with email and password.

http
POST /v1/auth/register

Body:

json
{
  "email": "user@example.com",
  "password": "securepassword123"
}

Response: 201 Created

json
{
  "data": {
    "id": "usr_abc123",
    "email": "user@example.com",
    "tier": "core",
    "email_verified": false
  }
}

INFO

Password must be at least 12 characters. A verification email is sent automatically. The verification link expires after 24 hours.

Errors:

CodeCondition
VALIDATION_ERRORPassword too short or invalid email format
CONFLICTEmail already registered

Login

Sign in with email and password.

http
POST /v1/auth/login

Body:

json
{
  "email": "user@example.com",
  "password": "securepassword123"
}

Response: 200 OK

json
{
  "data": {
    "access_token": "eyJhbGciOiJSUzI1NiIs...",
    "refresh_token": "rt_a1b2c3d4e5f6...",
    "expires_in": 900,
    "token_type": "Bearer"
  }
}

Errors:

CodeCondition
UNAUTHORIZEDInvalid email or password (generic message — does not reveal which field is wrong)
EMAIL_UNVERIFIEDAccount exists but email not verified
ACCOUNT_LOCKEDToo many failed attempts (5 in 15 minutes). Locked for 30 minutes.

Refresh Token

Exchange a valid refresh token for a new access token and refresh token.

http
POST /v1/auth/refresh

Body:

json
{
  "refresh_token": "rt_a1b2c3d4e5f6..."
}

Response: 200 OK

json
{
  "data": {
    "access_token": "eyJhbGciOiJSUzI1NiIs...",
    "refresh_token": "rt_new_token...",
    "expires_in": 900
  }
}

WARNING

The old refresh token is immediately invalidated after rotation. Using it again returns UNAUTHORIZED.

Logout

Revoke the current session.

http
POST /v1/auth/logout
Authorization: Bearer <jwt>

Response: 204 No Content

Email Verification

Verify Email

http
POST /v1/auth/verify-email

Body:

json
{
  "token": "verification_token_from_email"
}

Resend Verification Email

http
POST /v1/auth/resend-verification

Body:

json
{
  "email": "user@example.com"
}

Password Management

Forgot Password

Send a password reset email (link expires after 1 hour).

http
POST /v1/auth/forgot-password

Body:

json
{
  "email": "user@example.com"
}

Reset Password

http
POST /v1/auth/reset-password

Body:

json
{
  "token": "reset_token_from_email",
  "password": "new_secure_password"
}

Change Password

Requires the current password.

http
POST /v1/auth/change-password
Authorization: Bearer <jwt>

Body:

json
{
  "current_password": "old_password",
  "new_password": "new_secure_password"
}

Device Code Flow

Used by NexusIDE and NexusCore CLI to authenticate without a browser-based login form.

Step 1: Request Device Code

http
POST /v1/auth/device/code

Body:

json
{
  "client_type": "ide"
}

client_type can be "ide" or "cli".

Response: 200 OK

json
{
  "data": {
    "device_code": "dc_a1b2c3d4e5f6...",
    "user_code": "ABCD-1234",
    "verification_url": "https://nexus-suite.dev/device",
    "expires_in": 900,
    "interval": 5
  }
}

Step 2: User Authorizes in Browser

The user opens verification_url in a browser, enters the user_code, and signs in.

Step 3: Poll for Authorization

The client polls at the specified interval (minimum 5 seconds):

http
GET /v1/auth/device/poll/:device_code

Response (pending):

json
{
  "data": { "status": "pending" }
}

Response (authorized):

json
{
  "data": {
    "status": "authorized",
    "access_token": "eyJhbGciOiJSUzI1NiIs...",
    "refresh_token": "rt_a1b2c3d4e5f6..."
  }
}

Response (expired):

json
{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "expired_token"
  }
}

Step 4: Authorize a Device Code (Browser Side)

Called by the Portal when the user approves the device code:

http
POST /v1/auth/device/authorize
Authorization: Bearer <jwt>

Body:

json
{
  "user_code": "ABCD-1234"
}

OAuth

Google

http
GET /v1/auth/oauth/google

Redirects to Google's authorization endpoint with PKCE.

Google Callback

http
GET /v1/auth/oauth/google/callback?code=...&state=...

Processes the OAuth callback. Creates or links the account and redirects to the Portal dashboard.

GitHub

http
GET /v1/auth/oauth/github

Redirects to GitHub's authorization endpoint.

GitHub Callback

http
GET /v1/auth/oauth/github/callback?code=...&state=...

Link an additional OAuth provider to an existing account.

http
POST /v1/auth/link-oauth/:provider
Authorization: Bearer <jwt>

provider can be google or github.

Session Management

List Active Sessions

http
GET /v1/auth/sessions
Authorization: Bearer <jwt>

Response:

json
{
  "data": {
    "sessions": [
      {
        "id": "sess_abc123",
        "device_type": "ide",
        "device_name": "NexusIDE on MacBook Pro",
        "ip_address": "203.0.113.42",
        "location": "San Francisco, CA",
        "last_active_at": "2024-01-15T10:30:00Z",
        "created_at": "2024-01-10T08:00:00Z"
      }
    ]
  }
}

Revoke a Session

http
DELETE /v1/auth/sessions/:id
Authorization: Bearer <jwt>

Revoke All Sessions (Except Current)

http
DELETE /v1/auth/sessions
Authorization: Bearer <jwt>

User Profile

Get Current User

http
GET /v1/auth/me
Authorization: Bearer <jwt>

Response:

json
{
  "data": {
    "id": "usr_abc123",
    "email": "user@example.com",
    "display_name": "Jane Developer",
    "tier": "pro",
    "email_verified": true,
    "trial_eligible": false,
    "created_at": "2024-01-01T00:00:00Z"
  }
}

Update Profile

http
PATCH /v1/auth/me
Authorization: Bearer <jwt>

Body:

json
{
  "display_name": "Jane Developer"
}

Delete Account

http
DELETE /v1/auth/me
Authorization: Bearer <jwt>

DANGER

This permanently deletes the account, revokes all sessions, and cancels any active subscription. This action cannot be undone.

SSO (Studio Tier)

Configure SAML Identity Provider

http
POST /v1/auth/sso/configure
Authorization: Bearer <jwt>

Requires Studio tier admin role.

Body:

json
{
  "saml_metadata_url": "https://idp.example.com/metadata.xml"
}

Initiate SSO Login

http
POST /v1/auth/sso/login

Body:

json
{
  "org_slug": "my-organization"
}

JWKS Endpoint

http
GET /v1/auth/.well-known/jwks.json

Returns the public keys used to verify JWT signatures (RS256). Clients should cache this response with a 1-hour TTL.

Response:

json
{
  "keys": [
    {
      "kty": "RSA",
      "use": "sig",
      "alg": "RS256",
      "kid": "key-1",
      "n": "...",
      "e": "AQAB"
    }
  ]
}

JWT Payload Structure

json
{
  "sub": "usr_abc123",
  "email": "user@example.com",
  "tier": "pro",
  "org_id": null,
  "role": null,
  "iat": 1700000000,
  "exp": 1700000900,
  "iss": "https://api.nexus-suite.dev",
  "aud": "nexus-suite"
}
ClaimDescription
subUser ID
emailUser's email address
tierSubscription tier (core, pro, studio)
org_idOrganization ID (Studio tier, null otherwise)
roleOrganization role (admin, member, or null)
iatIssued at timestamp
expExpiration timestamp (15 minutes after issuance)
issIssuer (https://api.nexus-suite.dev)
audAudience (nexus-suite)

Released under the MIT License.