Skip to content

Errors

The AMP API uses conventional HTTP response codes and returns detailed error information in a consistent JSON format.

HTTP Status Codes

Code Description
200 Success
201 Created
204 No Content (successful deletion)
400 Bad Request - Invalid parameters
401 Unauthorized - Invalid or missing authentication
403 Forbidden - Valid auth but insufficient permissions
404 Not Found - Resource doesn't exist
409 Conflict - Resource state conflict
422 Unprocessable Entity - Validation failed
429 Too Many Requests - Rate limit exceeded
500 Internal Server Error
503 Service Unavailable - Temporary outage

Error Response Format

All errors follow this structure:

{
  "error": {
    "code": "error_code",
    "message": "Human-readable error message",
    "param": "field_name",
    "doc_url": "https://docs.amp.dev/api/errors#error_code",
    "request_id": "req_xxxxxxxxxxxx"
  }
}
Field Type Description
code string Machine-readable error code
message string Human-readable description
param string Parameter that caused the error (if applicable)
doc_url string Link to documentation for this error
request_id string Unique request ID for support

Error Codes

Authentication Errors

unauthorized

{
  "error": {
    "code": "unauthorized",
    "message": "Invalid or expired API key"
  }
}

Cause: Missing, invalid, or expired authentication.

Resolution: - Verify your API key is correct - Check if the key has expired - Ensure the Authorization header is properly formatted

forbidden

{
  "error": {
    "code": "forbidden",
    "message": "API key does not have required scope: missions:write"
  }
}

Cause: Valid authentication but insufficient permissions.

Resolution: - Check the scopes assigned to your API key - Create a new key with required scopes - Contact your tenant admin for elevated permissions

invalid_token

{
  "error": {
    "code": "invalid_token",
    "message": "JWT token is malformed or has invalid signature"
  }
}

Cause: The JWT token structure is invalid.

Resolution: - Obtain a fresh token via login - Verify token wasn't truncated during transmission


Request Errors

invalid_request

{
  "error": {
    "code": "invalid_request",
    "message": "The 'platforms' field is required",
    "param": "platforms"
  }
}

Cause: Request body is missing required fields or has invalid format.

Resolution: - Check required fields in API documentation - Verify JSON syntax is correct - Ensure Content-Type header is application/json

validation_error

{
  "error": {
    "code": "validation_error",
    "message": "Validation failed",
    "details": [
      {"field": "name", "message": "must be at least 3 characters"},
      {"field": "platforms", "message": "must contain valid platform identifiers"}
    ]
  }
}

Cause: One or more fields failed validation.

Resolution: - Review the details array for specific field errors - Correct each validation issue

invalid_parameter

{
  "error": {
    "code": "invalid_parameter",
    "message": "Invalid value for parameter 'status'. Expected one of: draft, active, paused, completed",
    "param": "status"
  }
}

Cause: Query parameter has invalid value.

Resolution: - Check allowed values in API documentation - Use exact values (case-sensitive)


Resource Errors

not_found

{
  "error": {
    "code": "not_found",
    "message": "Mission not found",
    "resource_type": "mission",
    "resource_id": "msn_invalid_id"
  }
}

Cause: The requested resource doesn't exist or isn't accessible.

Resolution: - Verify the resource ID is correct - Check if the resource belongs to your tenant - Resource may have been deleted

already_exists

{
  "error": {
    "code": "already_exists",
    "message": "API key with this name already exists",
    "param": "name"
  }
}

Cause: Attempting to create a resource that already exists.

Resolution: - Use a different name/identifier - Update the existing resource instead

conflict

{
  "error": {
    "code": "conflict",
    "message": "Cannot delete active mission. Pause or complete it first.",
    "current_state": "active",
    "allowed_states": ["draft", "paused", "completed"]
  }
}

Cause: Operation conflicts with current resource state.

Resolution: - Change resource state before retrying operation - Review state transition requirements


Rate Limiting Errors

rate_limit_exceeded

{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Rate limit exceeded. Retry after 45 seconds.",
    "retry_after": 45,
    "limit": 300,
    "current": 312
  }
}

Cause: Too many requests in the time window.

Resolution: - Wait for the retry_after duration - Implement exponential backoff - Consider upgrading your plan for higher limits

Headers returned:

X-RateLimit-Limit: 300
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1705319445
Retry-After: 45


Processing Errors

processing_failed

{
  "error": {
    "code": "processing_failed",
    "message": "Content generation failed after 3 attempts",
    "job_id": "job_xxx",
    "stage": "content",
    "cause": "provider_error"
  }
}

Cause: Background job processing failed.

Resolution: - Check job logs for details - Retry the operation - Contact support if issue persists

provider_error

{
  "error": {
    "code": "provider_error",
    "message": "LLM provider returned an error",
    "provider": "claude",
    "provider_error": "rate_limited",
    "retryable": true
  }
}

Cause: External provider (LLM, image gen) returned an error.

Resolution: - If retryable: true, wait and retry - Check provider status page - System will automatically try fallback providers

budget_exceeded

{
  "error": {
    "code": "budget_exceeded",
    "message": "Monthly AI budget limit reached",
    "limit_cents": 50000,
    "current_cents": 50234
  }
}

Cause: AI generation costs exceeded configured budget.

Resolution: - Increase budget limit in tenant settings - Wait for next billing period - Contact sales for limit increase


Server Errors

internal_error

{
  "error": {
    "code": "internal_error",
    "message": "An unexpected error occurred. Please try again.",
    "request_id": "req_xxxxxxxxxxxx"
  }
}

Cause: Unexpected server-side error.

Resolution: - Retry the request - If persistent, contact support with request_id

service_unavailable

{
  "error": {
    "code": "service_unavailable",
    "message": "Service temporarily unavailable. Please retry.",
    "retry_after": 30
  }
}

Cause: Temporary service disruption.

Resolution: - Wait and retry - Check status page for outage information


Handling Errors

Best Practices

  1. Always check HTTP status code first
  2. Parse the error response for details
  3. Log the request_id for debugging
  4. Implement retry logic for transient errors

Example Error Handler

async function callAmpApi(endpoint, options) {
  const response = await fetch(`https://api.amp.dev/v1${endpoint}`, {
    ...options,
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      'Content-Type': 'application/json',
      ...options.headers
    }
  });

  if (!response.ok) {
    const error = await response.json();

    switch (error.error.code) {
      case 'rate_limit_exceeded':
        const retryAfter = error.error.retry_after || 60;
        await sleep(retryAfter * 1000);
        return callAmpApi(endpoint, options); // Retry

      case 'unauthorized':
        throw new AuthError('API key invalid or expired');

      case 'not_found':
        throw new NotFoundError(error.error.message);

      default:
        throw new ApiError(error.error.message, error.error.code);
    }
  }

  return response.json();
}
import requests
import time

def call_amp_api(endpoint, method='GET', data=None):
    response = requests.request(
        method,
        f'https://api.amp.dev/v1{endpoint}',
        headers={'Authorization': f'Bearer {API_KEY}'},
        json=data
    )

    if not response.ok:
        error = response.json()['error']

        if error['code'] == 'rate_limit_exceeded':
            retry_after = error.get('retry_after', 60)
            time.sleep(retry_after)
            return call_amp_api(endpoint, method, data)

        elif error['code'] == 'unauthorized':
            raise AuthError('API key invalid or expired')

        elif error['code'] == 'not_found':
            raise NotFoundError(error['message'])

        else:
            raise ApiError(error['message'], error['code'])

    return response.json()
func callAmpAPI(endpoint string, method string, body io.Reader) ([]byte, error) {
    req, _ := http.NewRequest(method, "https://api.amp.dev/v1"+endpoint, body)
    req.Header.Set("Authorization", "Bearer "+apiKey)
    req.Header.Set("Content-Type", "application/json")

    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    data, _ := io.ReadAll(resp.Body)

    if resp.StatusCode >= 400 {
        var errResp ErrorResponse
        json.Unmarshal(data, &errResp)

        switch errResp.Error.Code {
        case "rate_limit_exceeded":
            retryAfter := errResp.Error.RetryAfter
            time.Sleep(time.Duration(retryAfter) * time.Second)
            return callAmpAPI(endpoint, method, body)
        case "unauthorized":
            return nil, ErrUnauthorized
        case "not_found":
            return nil, ErrNotFound
        default:
            return nil, fmt.Errorf("%s: %s", errResp.Error.Code, errResp.Error.Message)
        }
    }

    return data, nil
}

Retry Strategy

For transient errors, implement exponential backoff:

async function withRetry(fn, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await fn();
    } catch (error) {
      if (!isRetryable(error) || attempt === maxRetries - 1) {
        throw error;
      }
      const delay = Math.min(1000 * Math.pow(2, attempt), 30000);
      await sleep(delay);
    }
  }
}

function isRetryable(error) {
  const retryableCodes = [
    'rate_limit_exceeded',
    'service_unavailable',
    'internal_error',
    'provider_error'
  ];
  return retryableCodes.includes(error.code);
}

Getting Help

If you encounter persistent errors:

  1. Check the status page for outages
  2. Search the community forum
  3. Contact support with your request_id