Skip to main content

Overview

The Pipeline API uses JWT (JSON Web Token) based authentication. After signing up and logging in, you’ll receive a session token that must be included in the Authorization header for all authenticated requests.

Authentication Flow

The typical authentication flow follows these steps:
  1. Signup - Create a new account with email and password
  2. Email Confirmation - Confirm your email address (check your inbox)
  3. Login - Sign in to receive a session token
  4. Make Authenticated Requests - Include the token in subsequent API calls
  5. Logout - End your session when done

Signup

Create a new account by providing an email and password.

Endpoint

POST /api/auth/signup

Request Body

email
string
required
Valid email address (will be normalized to lowercase)
password
string
required
Password meeting security requirements (minimum 8 characters recommended)
redirect_to
string
Custom URL to redirect to after email confirmation (optional)

Response

user
object
Created user object
user.id
string
Unique user identifier (UUID)
user.email
string
User’s email address
message
string
Instructions for next steps (e.g., “Check your email to confirm your account”)

Example

curl -X POST https://api.pipeline.local/api/auth/signup \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]",
    "password": "SecureP@ssw0rd!"
  }'

Success Response (201)

{
  "user": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "email": "[email protected]"
  },
  "message": "Check your email to confirm your account"
}

Error Responses

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid input",
    "details": [
      {
        "field": "email",
        "message": "Invalid email address"
      }
    ]
  }
}
{
  "error": {
    "code": "WEAK_PASSWORD",
    "message": "Password does not meet security requirements."
  }
}
{
  "error": {
    "code": "EMAIL_TAKEN",
    "message": "An account with this email already exists."
  }
}
{
  "error": {
    "code": "RATE_LIMITED",
    "message": "Too many signup attempts. Please try again later."
  }
}

Login

Sign in with your email and password to obtain a session token.

Endpoint

POST /api/auth/login

Request Body

email
string
required
Your email address
password
string
required
Your password

Response

user
object
Authenticated user object
user.id
string
User identifier (UUID)
user.email
string
User’s email address
Session Management: The API automatically sets secure, HTTP-only cookies containing your session token. You don’t need to manually extract or store tokens - just include credentials in subsequent requests and cookies will be sent automatically.

Example

curl -X POST https://api.pipeline.local/api/auth/login \
  -H "Content-Type: application/json" \
  -c cookies.txt \
  -d '{
    "email": "[email protected]",
    "password": "SecureP@ssw0rd!"
  }'

Success Response (200)

{
  "user": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "email": "[email protected]"
  }
}

Error Responses

{
  "error": {
    "code": "INVALID_CREDENTIALS",
    "message": "Invalid email or password"
  }
}
{
  "error": {
    "code": "EMAIL_NOT_CONFIRMED",
    "message": "Please confirm your email before logging in"
  }
}

Making Authenticated Requests

After logging in, include your session token in the Authorization header for all protected endpoints.

Using Bearer Token

If you’re managing tokens manually (e.g., from a custom auth implementation):
curl -X GET https://api.pipeline.local/api/jobs \
  -H "Authorization: Bearer YOUR_JWT_TOKEN_HERE"
When using the standard login flow, cookies are handled automatically:
# Use -b to send cookies from login
curl -X GET https://api.pipeline.local/api/jobs \
  -b cookies.txt

Logout

End your session and invalidate the authentication token.

Endpoint

POST /api/auth/logout

Headers

Authorization
string
required
Bearer token or session cookie from login

Response

success
boolean
Always true on successful logout

Example

curl -X POST https://api.pipeline.local/api/auth/logout \
  -b cookies.txt

Success Response (200)

{
  "success": true
}

Session Management

Token Expiration

JWT tokens have a limited lifetime. When a token expires, you’ll receive a 401 Unauthorized response and need to log in again.

Token Storage

Security Best Practice: Session tokens are stored in secure, HTTP-only cookies to prevent XSS attacks. Never store tokens in localStorage or expose them to client-side JavaScript if possible.

Handling Authentication Errors

When you receive a 401 Unauthorized response:
  1. Clear any stored session data
  2. Redirect the user to the login page
  3. After successful login, retry the original request
async function fetchWithAuth(url, options = {}) {
  const response = await fetch(url, {
    ...options,
    credentials: 'include',
  });
  
  if (response.status === 401) {
    // Session expired - redirect to login
    window.location.href = '/login';
    return null;
  }
  
  return response.json();
}

Rate Limits

Authentication endpoints have strict rate limits to prevent brute force attacks:
  • 5 requests per minute per IP address
If you exceed this limit, you’ll receive a 429 Too Many Requests response:
{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Too many requests. Please try again in 60 seconds.",
    "retry_after": 60
  }
}

Error Codes Reference

CodeHTTP StatusDescription
VALIDATION_ERROR400Invalid request format or parameters
INVALID_EMAIL400Email address format is invalid
WEAK_PASSWORD400Password doesn’t meet security requirements
INVALID_CREDENTIALS401Email or password is incorrect
UNAUTHORIZED401No valid session found
EMAIL_NOT_CONFIRMED403Account email not yet confirmed
SIGNUPS_DISABLED403New registrations temporarily disabled
EMAIL_TAKEN409Account with this email already exists
RATE_LIMITED429Too many authentication attempts
INTERNAL_ERROR500Unexpected server error

Security Considerations

HTTPS Required

Always use HTTPS in production to protect credentials in transit

Secure Storage

Tokens are stored in HTTP-only cookies to prevent XSS attacks

Rate Limiting

Brute force protection with IP-based rate limits

Email Normalization

Emails are normalized to lowercase to prevent duplicates

Next Steps

Jobs API

Start managing job applications with the Jobs API

API Overview

Learn about request formats and error handling

Build docs developers (and LLMs) love