REST API Reference

For teams not using Next.js, VibeLogin provides a complete REST API. All SDK functionality is available via HTTP endpoints. This reference covers every endpoint you need to integrate VibeLogin into any backend or client.

Base URL

https://api.vibelogin.com

Authentication

VibeLogin uses two types of API keys. Which key you use depends on whether the request originates from the client or server.

Key TypeHeaderUse Case
Publishable Keyx-publishable-key: pk_live_xxxClient-side requests (signup, signin forms)
Secret KeyAuthorization: Bearer sk_live_xxxServer-side requests (token exchange, user management)

Keep your secret key safe

Never expose your secret key in client-side code or public repositories. The secret key should only be used in server-side requests.

Hosted Auth Endpoints

These are the public-facing endpoints that power VibeLogin's hosted login flow. They use your project's slug in the URL path. No secret key is required — the project is identified by the slug.

All hosted auth endpoints return a one-time authorization code on success. Your backend exchanges this code for tokens using the POST /v1/auth/oauth/token endpoint with your secret key.

POST /:slug/signup

Register a new user with email and password. Returns a one-time auth code on success. If the email already exists, returns a generic success message for anti-enumeration protection.

Request Body

{
  "email": "user@example.com",
  "password": "securepassword123",
  "name": "Jane Doe",
  "metadata": { "plan": "pro" },
  "redirectUrl": "https://yourapp.com/auth/callback"
}
FieldTypeRequiredDescription
emailstringYesValid email address
passwordstringYesMinimum 8 characters
namestringNoDisplay name (max 255 chars)
metadataobjectNoArbitrary JSON metadata
redirectUrlstringYesMust be in your project's allowed redirect URLs

Response 201

{ "code": "vl_code_abc123..." }

Example

curl -X POST https://api.vibelogin.com/hosted/my-app/signup \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "password": "securepassword123",
    "name": "Jane Doe",
    "redirectUrl": "https://yourapp.com/auth/callback"
  }'

POST /:slug/signin

Sign in with email and password. Returns a one-time auth code on success. Uses generic error messages for anti-enumeration protection.

Request Body

{
  "email": "user@example.com",
  "password": "securepassword123",
  "redirectUrl": "https://yourapp.com/auth/callback"
}
FieldTypeRequiredDescription
emailstringYesValid email address
passwordstringYesUser password
redirectUrlstringYesMust be in your project's allowed redirect URLs

Response 200

{ "code": "vl_code_abc123..." }

Example

curl -X POST https://api.vibelogin.com/hosted/my-app/signin \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "password": "securepassword123",
    "redirectUrl": "https://yourapp.com/auth/callback"
  }'

POST /:slug/magic-link

Send a magic link to the user's email address. The link expires after 15 minutes. Always returns a generic success message regardless of whether the email exists (anti-enumeration).

Request Body

{
  "email": "user@example.com",
  "redirectUrl": "https://yourapp.com/auth/callback"
}

Response 200

{
  "message": "If an account exists with this email, a magic link has been sent."
}

Example

curl -X POST https://api.vibelogin.com/hosted/my-app/magic-link \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "redirectUrl": "https://yourapp.com/auth/callback"
  }'

POST /:slug/magic-link/verify

Verify a magic link token and receive a one-time auth code. The token is single-use and expires after 15 minutes.

Request Body

{
  "token": "vl_tok_abc123...",
  "redirectUrl": "https://yourapp.com/auth/callback"
}

Response 200

{ "code": "vl_code_abc123..." }

Example

curl -X POST https://api.vibelogin.com/hosted/my-app/magic-link/verify \
  -H "Content-Type: application/json" \
  -d '{
    "token": "vl_tok_abc123...",
    "redirectUrl": "https://yourapp.com/auth/callback"
  }'

POST /:slug/password/reset-request

Request a password reset email. The reset link expires after 15 minutes. Always returns a generic success message regardless of whether the email exists (anti-enumeration).

Request Body

{
  "email": "user@example.com",
  "redirectUrl": "https://yourapp.com/auth/callback"
}

Response 200

{
  "message": "If an account exists, a password reset link has been sent."
}

Example

curl -X POST https://api.vibelogin.com/hosted/my-app/password/reset-request \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "redirectUrl": "https://yourapp.com/auth/callback"
  }'

POST /:slug/password/reset

Complete a password reset using the token from the reset email. Sets the new password and returns a one-time auth code so the user is automatically signed in.

Request Body

{
  "token": "vl_tok_reset123...",
  "password": "newsecurepassword456",
  "redirectUrl": "https://yourapp.com/auth/callback"
}
FieldTypeRequiredDescription
tokenstringYesToken from the password reset email
passwordstringYesNew password (minimum 8 characters)
redirectUrlstringYesMust be in your project's allowed redirect URLs

Response 200

{ "code": "vl_code_abc123..." }

Example

curl -X POST https://api.vibelogin.com/hosted/my-app/password/reset \
  -H "Content-Type: application/json" \
  -d '{
    "token": "vl_tok_reset123...",
    "password": "newsecurepassword456",
    "redirectUrl": "https://yourapp.com/auth/callback"
  }'

POST /:slug/email/request-verify

Request an email verification link. The verification token expires after 24 hours. Returns a generic message regardless of whether the email exists.

Request Body

{
  "email": "user@example.com",
  "redirectUrl": "https://yourapp.com/auth/callback"
}

Response 200

{
  "message": "If an account exists, a verification email has been sent."
}

Example

curl -X POST https://api.vibelogin.com/hosted/my-app/email/request-verify \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "redirectUrl": "https://yourapp.com/auth/callback"
  }'

POST /:slug/email/verify

Verify an email address using the token from the verification email. Marks the user's email as verified.

Request Body

{
  "token": "vl_tok_verify123..."
}

Response 200

{ "message": "Email verified successfully." }

Example

curl -X POST https://api.vibelogin.com/hosted/my-app/email/verify \
  -H "Content-Type: application/json" \
  -d '{ "token": "vl_tok_verify123..." }'

Token Exchange

After a successful signup, signin, or magic link verification, your backend must exchange the one-time authorization code for access and refresh tokens. This is the critical step for non-SDK integrations.

POST /v1/auth/oauth/token

Exchange a one-time authorization code for access and refresh tokens. This endpoint requires your secret key. The code is single-use and expires after a short window.

Server-side only

This endpoint requires your secret key. Call it from your backend, never from the browser.

Request Body

{
  "code": "vl_code_abc123..."
}

Response 200

{
  "accessToken": "eyJhbGciOiJFZERTQSIs...",
  "refreshToken": "vl_rt_abc123...",
  "isNewUser": false
}
FieldTypeDescription
accessTokenstringJWT access token (default 15 min expiry)
refreshTokenstringOpaque refresh token (default 7 day expiry)
isNewUserbooleanWhether the user was just created (useful for onboarding flows)

Example

curl -X POST https://api.vibelogin.com/v1/auth/oauth/token \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk_live_your_secret_key" \
  -d '{ "code": "vl_code_abc123..." }'

Full authentication flow

1. User submits credentials to POST /:slug/signin and receives a one-time code.
2. Your frontend redirects to your callback URL with the code as a query parameter.
3. Your backend calls POST /v1/auth/oauth/token with the code and your secret key.
4. Store the tokens — set the access token as a cookie and save the refresh token server-side.

POST /v1/auth/refresh

Exchange a refresh token for a new access token and refresh token pair. The old refresh token is invalidated (rotation). Requires your secret key.

Request Body

{
  "refreshToken": "vl_rt_abc123..."
}

Response 200

{
  "accessToken": "eyJhbGciOiJFZERTQSIs...",
  "refreshToken": "vl_rt_newtoken456..."
}

Example

curl -X POST https://api.vibelogin.com/v1/auth/refresh \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk_live_your_secret_key" \
  -d '{ "refreshToken": "vl_rt_abc123..." }'

JWKS Endpoint

GET /v1/jwks/:projectId

Returns the project's public keys in standard JWKS format (RFC 7517). Use this endpoint to configure your JWT verification library so it can validate access tokens locally without calling the API on every request. No authentication required.

This is how the VibeLogin SDK validates tokens — it fetches the JWKS once and caches it. Your backend can do the same with any JWT library that supports JWKS endpoints.

Response 200

{
  "keys": [
    {
      "kty": "OKP",
      "crv": "Ed25519",
      "x": "base64url-encoded-public-key",
      "kid": "key-id-uuid",
      "use": "sig",
      "alg": "EdDSA"
    }
  ]
}

Example

curl https://api.vibelogin.com/v1/jwks/your-project-uuid

Caching

The response includes Cache-Control: public, max-age=3600 so your JWT library can cache the keys for up to 1 hour. This means token verification adds zero latency after the initial fetch.

Error Responses

All errors follow a consistent format with an error message and machine-readable error code:

{
  "error": "Invalid email or password.",
  "code": "INVALID_CREDENTIALS"
}
StatusMeaningExample Code
400Bad request (validation error, invalid token)VALIDATION_ERROR, INVALID_TOKEN
401Unauthorized (invalid credentials, missing auth)INVALID_CREDENTIALS
403Forbidden (banned user, expired token)ACCOUNT_BANNED
404Not found (invalid slug, project not found)INVALID_REQUEST
409Conflict (duplicate email)DUPLICATE_EMAIL
429Rate limitedRATE_LIMITED
503Service unavailable (email delivery failed)EMAIL_FAILED

Rate Limits

Rate limits are applied per IP address to prevent abuse. If you exceed a limit, the API returns 429 Too Many Requests.

Endpoint CategoryLimitWindow
Auth (signup, signin)10 requests15 minutes per IP
Email (magic-link, password reset, verify)5 requests15 minutes per IP
Token refresh30 requests15 minutes per IP

Handling rate limits

Rate limits are per-IP. If you hit a limit, wait and retry. The response includes a Retry-After header indicating how many seconds to wait before retrying.