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¶
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:
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¶
- Always check HTTP status code first
- Parse the error response for details
- Log the
request_idfor debugging - 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:
- Check the status page for outages
- Search the community forum
- Contact support with your
request_id