Skip to main content

Overview

PIPELINE API uses standard HTTP status codes and detailed error codes to help you understand and handle errors effectively. All errors follow a consistent response format.
Every error response includes a requestId for troubleshooting and support. Include this ID when reporting issues.

Error Response Format

All API errors return JSON responses in this format:
{
  "code": "ERROR_CODE",
  "status": 400,
  "message": "Human-readable error message",
  "details": {
    "additional": "context"
  },
  "errors": [
    {
      "field": "company_name",
      "message": "Company name is required",
      "value": ""
    }
  ],
  "requestId": "req_abc123",
  "timestamp": "2026-03-04T12:00:00Z",
  "apiVersion": "1.0"
}

Response Fields

code
string
required
Machine-readable error code (e.g., UNAUTHORIZED, JOB_NOT_FOUND)
status
number
required
HTTP status code (e.g., 400, 401, 404, 500)
message
string
required
Human-readable error description
details
object
Additional context about the error (varies by error type)
errors
array
Field-level validation errors (for validation failures)
requestId
string
Unique request identifier for tracing and support
timestamp
string
required
ISO 8601 timestamp when the error occurred
apiVersion
string
required
API version (currently “1.0”)

Error Categories

Authentication (401)

9 error codes for authentication failures

Authorization (403)

3 error codes for permission issues

Not Found (404)

6 error codes for missing resources

Validation (400)

8 error codes for invalid input

Rate Limits (429)

3 error codes for rate limiting

Conflicts (409)

3 error codes for state conflicts

Server Errors (500)

5 error codes for server issues

Service Unavailable (503)

6 error codes for service failures

Authentication Errors (401)

Status: 401Description: No valid authentication providedCommon Causes:
  • Missing Authorization header
  • Invalid or expired JWT token
  • Malformed token
Solution: Check authentication, re-login if needed
{
  "code": "UNAUTHORIZED",
  "status": 401,
  "message": "Authentication required"
}
Status: 401Description: Email or password is incorrectSolution: Verify credentials, use password reset if needed
Status: 401Description: Email address has not been confirmedSolution: Check email for confirmation link, request new one
Status: 401Description: Session has expiredSolution: Re-authenticate
Status: 401Description: Token has expired (typically after 1 hour)Solution: Refresh token or re-authenticate

Validation Errors (400)

Validation errors include detailed field-level information:
{
  "code": "VALIDATION_ERROR",
  "status": 400,
  "message": "Request validation failed",
  "errors": [
    {
      "field": "company_name",
      "message": "Company name is required",
      "value": ""
    },
    {
      "field": "job_title",
      "message": "Job title must be at least 2 characters",
      "value": "a"
    },
    {
      "field": "url",
      "message": "Must be a valid HTTPS URL",
      "value": "invalid-url"
    }
  ]
}

Field Error Structure

field
string
required
Field name using dot notation for nested fields (e.g., user.email)
message
string
required
Field-specific error message
code
string
Field-level error code (optional)
value
any
The invalid value that was provided

Common Validation Errors

CodeDescription
VALIDATION_ERRORGeneral validation failure
INVALID_INPUTInput format is invalid
INVALID_URLURL format is invalid
INVALID_EMAILEmail format is invalid
MISSING_REQUIRED_FIELDRequired field is missing
FIELD_TOO_LONGField exceeds maximum length
DUPLICATE_RESOURCEResource already exists

Invalid Status Transitions

Job status changes must follow valid transitions:
{
  "code": "INVALID_STATUS_TRANSITION",
  "status": 400,
  "message": "Cannot transition from 'offer' to 'applied'",
  "details": {
    "from": "offer",
    "to": "applied",
    "allowed": ["rejected"]
  }
}
Valid Transitions:
  • savedapplied, rejected
  • appliedinterview, rejected
  • interviewoffer, rejected
  • offerrejected
  • rejectedsaved (re-apply)

Rate Limit Errors (429)

See the Rate Limits page for detailed information.
{
  "code": "RATE_LIMIT_EXCEEDED",
  "status": 429,
  "message": "Rate limit exceeded",
  "details": {
    "retryAfter": 60,
    "limit": 100,
    "remaining": 0,
    "resetAt": "2026-03-04T12:01:00Z"
  }
}

Not Found Errors (404)

Resource-specific not found errors include the resource type and ID:
{
  "code": "JOB_NOT_FOUND",
  "status": 404,
  "message": "Job not found",
  "details": {
    "resourceType": "Job",
    "resourceId": "123e4567-e89b-12d3-a456-426614174000"
  }
}
CodeResource Type
JOB_NOT_FOUNDJob
USER_NOT_FOUNDUser
EVENT_NOT_FOUNDEvent
INSIGHT_NOT_FOUNDInsight
SCRAPER_RUN_NOT_FOUNDScraper Run

Server Errors (500)

Server errors (5xx) are logged automatically. If you encounter persistent server errors, check your configuration and contact support.

Common Server Errors

Status: 500Description: Database operation failedCommon Causes:
  • Connection issues
  • Query timeout
  • Constraint violation
Solution: Retry later, check database connection
{
  "code": "DATABASE_ERROR",
  "status": 500,
  "message": "Database operation failed",
  "details": {
    "table": "jobs",
    "constraint": "check_salary_range"
  }
}
Status: 500Description: Internal server errorSolution: Retry later, contact support if persistent
Status: 500Description: Export operation failedSolution: Check filters and retry
Status: 500Description: Import operation failedSolution: Check file format and data

Service Unavailable (503)

External services may be temporarily unavailable:

AI Service Errors

{
  "code": "AI_SERVICE_TIMEOUT",
  "status": 503,
  "message": "AI service timed out",
  "details": {
    "provider": "openai",
    "model": "gpt-4",
    "timeoutMs": 30000
  }
}

Scraper Errors

{
  "code": "SCRAPER_TIMEOUT",
  "status": 503,
  "message": "Scraper timed out",
  "details": {
    "source": "linkedin",
    "url": "https://linkedin.com/jobs/search",
    "timeoutMs": 60000,
    "retryable": true
  }
}

Discord Webhook Errors

{
  "code": "DISCORD_WEBHOOK_ERROR",
  "status": 503,
  "message": "Discord webhook failed",
  "details": {
    "serviceName": "Discord",
    "externalErrorCode": "50001"
  }
}

Error Handling

TypeScript Type Guards

Use type guards to handle specific error types:
import { ApiErrorResponse } from '@/types';

function isAuthenticationError(error: ApiErrorResponse): boolean {
  return error.status === 401;
}

function isValidationError(error: ApiErrorResponse): boolean {
  return error.status === 400 || error.code === 'DUPLICATE_RESOURCE';
}

function isRateLimitError(error: ApiErrorResponse): boolean {
  return error.status === 429;
}

function isRetryableError(error: ApiErrorResponse): boolean {
  return (
    error.status === 429 ||  // Rate limit
    error.status === 503 ||  // Service unavailable
    error.code === 'SCRAPER_TIMEOUT' ||
    error.code === 'AI_SERVICE_TIMEOUT'
  );
}

React Hook Example

import { useState } from 'react';

export function useApiError() {
  const [error, setError] = useState<ApiErrorResponse | null>(null);
  
  const handleError = (err: ApiErrorResponse) => {
    setError(err);
    
    // Handle specific error types
    if (isAuthenticationError(err)) {
      // Redirect to login
      router.push('/login');
    } else if (isValidationError(err)) {
      // Show field-level errors
      err.errors?.forEach(fieldError => {
        showError(fieldError.field, fieldError.message);
      });
    } else if (isRateLimitError(err)) {
      // Show retry timer
      const retryAfter = err.details?.retryAfter;
      showRetryMessage(retryAfter);
    }
  };
  
  return { error, handleError };
}

Best Practices

Always check the code field, not just the HTTP status:
if (error.code === 'JOB_NOT_FOUND') {
  // Handle specifically
}
Show field-level validation errors next to form fields:
error.errors?.forEach(({ field, message }) => {
  setFieldError(field, message);
});
Retry retryable errors with exponential backoff:
if (isRetryableError(error)) {
  await retryWithBackoff(operation);
}
Include requestId in error logs and support tickets:
console.error(`Error ${error.code} [${error.requestId}]`);
Never expose raw error details to end users:
const userMessage = error.status >= 500
  ? 'Something went wrong. Please try again.'
  : error.message;

Troubleshooting

1

Check the Error Code

Use the specific error code to understand what went wrong
2

Review the Details

Check the details object for additional context
3

Check Rate Limits

Verify you haven’t exceeded rate limits (see headers)
4

Retry if Retryable

Use exponential backoff for 429 and 503 errors
5

Contact Support

Include the requestId when reporting persistent issues

Rate Limits

Learn about API rate limiting

Webhooks

Webhook error handling

Build docs developers (and LLMs) love