Skip to main content
When a request fails, the Avala API returns an appropriate HTTP status code along with a JSON body describing the error. Use the status code to determine the category of failure and the response body for specifics.

Standard Error Response

Most errors return a JSON object with a detail field:
{
  "detail": "A human-readable description of the error."
}
Some endpoints return structured errors with a machine-readable code and a link to the relevant documentation:
{
  "detail": "Project approval requires a PRO or ENTERPRISE plan.",
  "code": "plan_insufficient",
  "doc_url": "https://docs.avala.ai/api/errors#plan_insufficient"
}
Use the code field for programmatic error handling in your pipeline. The detail field is human-readable and may change between versions.

Validation Errors

Requests that fail input validation return a 400 status code with field-specific error details:
{
  "detail": {
    "name": ["This field is required."],
    "email": ["Enter a valid email address."]
  }
}
Each key corresponds to a request field, and the value is an array of error messages for that field.

Error Code Reference

Status CodeNameDescription
400Bad RequestThe request body is invalid, malformed, or missing required fields.
401UnauthorizedAuthentication failed — the API key is missing, invalid, or expired.
403ForbiddenThe authenticated key does not have permission to perform this action.
404Not FoundThe requested resource does not exist or has been deleted.
405Method Not AllowedThe HTTP method is not supported for this endpoint.
409ConflictThe request conflicts with the current state of the resource (e.g., duplicate name).
413Payload Too LargeThe request body exceeds the maximum allowed size.
429Too Many RequestsRate limit exceeded. Back off and retry after the window resets.
500Internal Server ErrorAn unexpected error occurred on the server.
503Service UnavailableThe API is temporarily offline for maintenance or under heavy load.

Detailed Error Descriptions

400 — Bad Request

The request is malformed or contains invalid data. Common causes:
  • Missing a required field in the request body
  • Sending an invalid data type (e.g., string where an integer is expected)
  • Malformed JSON in the request body
{
  "detail": {
    "name": ["This field is required."],
    "schedule": ["Invalid cron expression."]
  }
}
Remediation: Check the request body against the endpoint’s schema. Ensure all required fields are present and correctly typed.

401 — Unauthorized

Authentication failed. Common causes:
  • No X-Avala-Api-Key header included in the request
  • The API key is invalid or has been revoked
  • The API key has expired
{
  "detail": "Invalid API key."
}
Remediation: Verify your API key is correct and active. Generate a new key from Mission Control if needed. See Authentication.

403 — Forbidden

The API key is valid but lacks permission for the requested action. Common causes:
  • Attempting to access a resource owned by a different organization
  • Insufficient role or permission level for the operation
  • API key is missing a required scope
  • Organization plan does not include the requested feature
{
  "detail": "You do not have permission to perform this action."
}
Remediation: Confirm the resource belongs to your organization. Contact your team admin if you need elevated permissions.

Structured Error Codes

Some 403 responses include a machine-readable code for programmatic handling: plan_insufficient — Your organization’s plan does not support this action. Upgrade to PRO or ENTERPRISE to access this feature.
{
  "detail": "Project approval requires a PRO or ENTERPRISE plan.",
  "code": "plan_insufficient",
  "doc_url": "https://docs.avala.ai/api/errors#plan_insufficient"
}
Remediation: Contact your Avala account manager to upgrade your organization’s plan. scope_required — Your API key does not include the required scope for this action.
{
  "detail": "API key requires 'projects.write' scope.",
  "code": "scope_required",
  "doc_url": "https://docs.avala.ai/api/errors#scope_required"
}
Remediation: Create a new API key with the required scope from Settings > Security in Mission Control. See API Key Scopes for the full list.

404 — Not Found

The requested resource does not exist. Common causes:
  • The resource ID is incorrect or misspelled
  • The resource was previously deleted
  • The URL path is wrong
{
  "detail": "Not found."
}
Remediation: Verify the resource ID and endpoint path. List resources to confirm the ID exists.

405 — Method Not Allowed

The HTTP method is not supported on the endpoint. Common causes:
  • Sending a PATCH request to an endpoint that only supports GET and POST
  • Using DELETE on a resource that does not support deletion
{
  "detail": "Method \"PATCH\" not allowed."
}
Remediation: Check the API reference for the supported methods on the endpoint.

409 — Conflict

The request conflicts with the current state of a resource. Common causes:
  • Creating a resource with a name that already exists
  • Attempting a state transition that is not allowed (e.g., re-activating a completed run)
{
  "detail": "An agent with this name already exists."
}
Remediation: Change the conflicting field value, or fetch the existing resource and update it instead.

413 — Payload Too Large

The request body exceeds the maximum allowed size. Common causes:
  • Uploading a file that exceeds the size limit
  • Sending an excessively large JSON payload
{
  "detail": "Request body too large. Maximum size is 100MB."
}
Remediation: Reduce the payload size. For file uploads, compress the file or split it into smaller parts.

429 — Too Many Requests

You have exceeded the rate limit. Common causes:
  • Sending more than 100 requests per minute
  • Exceeding concurrent upload or export limits
{
  "detail": "Request was throttled. Expected available in 12 seconds."
}
The response includes rate limit headers:
HeaderDescription
X-RateLimit-LimitMaximum requests allowed in the current window
X-RateLimit-RemainingRequests remaining in the current window
X-RateLimit-ResetUnix timestamp when the window resets
Remediation: Wait until the rate limit window resets, then retry. Implement exponential backoff in your client.

500 — Internal Server Error

An unexpected error occurred on the server. Common causes:
  • A bug or transient failure in the Avala backend
{
  "detail": "Internal server error."
}
Remediation: Retry the request after a brief delay. If the error persists, contact support@avala.ai with the request details.

503 — Service Unavailable

The API is temporarily unable to handle requests. Common causes:
  • Scheduled maintenance
  • The service is under heavy load
{
  "detail": "Service temporarily unavailable. Please try again later."
}
Remediation: Wait and retry with exponential backoff. Check the Avala status page for incident updates.

Handling Errors

Implement retry logic with exponential backoff for transient errors (429, 500, 503). Do not retry client errors (400, 401, 403, 404).
Python
import time
import requests

def request_with_retry(method, url, headers, json=None, max_retries=3):
    """Make an API request with exponential backoff for transient errors."""
    retryable_status_codes = {429, 500, 503}

    for attempt in range(max_retries + 1):
        response = requests.request(
            method, url, headers=headers, json=json
        )

        if response.status_code not in retryable_status_codes:
            return response

        if attempt == max_retries:
            return response

        # Use Retry-After or X-RateLimit-Reset if available
        retry_after = response.headers.get("Retry-After")
        if retry_after:
            wait = int(retry_after)
        else:
            wait = 2 ** attempt  # 1s, 2s, 4s

        print(f"Request failed with {response.status_code}. "
              f"Retrying in {wait}s (attempt {attempt + 1}/{max_retries})...")
        time.sleep(wait)

    return response


# Usage
response = request_with_retry(
    method="GET",
    url="https://api.avala.ai/api/v1/datasets/",
    headers={"X-Avala-Api-Key": "avk_your_api_key"},
)

if response.ok:
    data = response.json()
else:
    print(f"Error {response.status_code}: {response.json()['detail']}")

Handling Structured Error Codes

Some endpoints return structured errors with a code field for programmatic handling. Use the code to take specific actions in your pipeline:
response = requests.post(
    f"https://api.avala.ai/api/v1/projects/{project_uid}/approve/",
    headers={"X-Avala-Api-Key": API_KEY},
)

if response.ok:
    project = response.json()
    print(f"Approved: {project['name']}")
else:
    error = response.json()
    code = error.get("code")

    if code == "plan_insufficient":
        # Organization needs a plan upgrade
        notify_ops("Plan upgrade needed for project approval")
    elif code == "scope_required":
        # API key is missing a required scope
        notify_ops(f"API key needs scope: {error['detail']}")
    elif response.status_code == 400:
        # Invalid state transition (e.g., project already active)
        log.warning(f"Cannot approve: {error['detail']}")
    elif response.status_code == 404:
        # Project not found or not owned by this user
        log.error(f"Project {project_uid} not found")

Error Recovery Decision Tree

API call fails
  |
  +-- 401 Unauthorized
  |     -> API key invalid or expired. Rotate key. Do NOT retry.
  |
  +-- 403 Forbidden
  |     +-- code: "plan_insufficient" -> Upgrade org plan. Do NOT retry.
  |     +-- code: "scope_required"    -> Create new key with scope. Do NOT retry.
  |     +-- (no code)                 -> Wrong owner/org. Do NOT retry.
  |
  +-- 404 Not Found
  |     -> Check resource UID. Do NOT retry.
  |
  +-- 400 Bad Request
  |     -> Fix request body or check resource state. Do NOT retry.
  |
  +-- 429 Too Many Requests
  |     -> Wait for Retry-After header, then retry.
  |
  +-- 500 / 503
        -> Retry with exponential backoff (1s, 2s, 4s).