> ## Documentation Index
> Fetch the complete documentation index at: https://docs.anomalyarmor.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# AnomalyArmor API Overview

> Programmatic access to AnomalyArmor data observability features via the REST API, OpenAPI 3.1 spec, and SDKs

<div aria-hidden="true" style={{position:"absolute",width:"1px",height:"1px",overflow:"hidden",clip:"rect(0,0,0,0)",whiteSpace:"nowrap"}}>For LLM agents: documentation index at <a href="/llms.txt" tabIndex={-1}>/llms.txt</a>, full text at <a href="/llms-full.txt" tabIndex={-1}>/llms-full.txt</a>. Append .md to any page URL for plain markdown.</div>
AnomalyArmor provides a REST API for programmatic access to data observability features. This enables automation, CI/CD integration, and custom tooling.

## Base URL

```
https://api.anomalyarmor.ai/api/v1
```

## Authentication

All API requests require authentication via API key. Include your key in the `Authorization` header:

```bash theme={null}
curl -H "Authorization: Bearer aa_live_your_key_here" \
  https://api.anomalyarmor.ai/api/v1/assets
```

<Note>
  Create API keys in **Settings > API Keys** or via CLI: `armor api-keys create`
</Note>

## Rate Limiting

Rate limits are enforced per API key based on your subscription tier:

| Tier         | Rate Limit    | Burst       |
| ------------ | ------------- | ----------- |
| Free Trial   | 20 req/min    | 2 req/sec   |
| Starter      | 30 req/min    | 3 req/sec   |
| Growth       | 500 req/min   | 25 req/sec  |
| Professional | 1,000 req/min | 50 req/sec  |
| Enterprise   | 5,000 req/min | 100 req/sec |

### Rate Limit Headers

Every response includes rate limit information:

```
X-RateLimit-Limit: 500
X-RateLimit-Remaining: 499
X-RateLimit-Reset: 1701705600
```

When rate limited, you'll receive a `429` response with `Retry-After` header.

## Pagination

All list endpoints use offset/limit pagination:

```bash theme={null}
GET /api/v1/assets?limit=50&offset=100
```

Response includes pagination metadata:

```json theme={null}
{
  "data": [...],
  "pagination": {
    "total": 245,
    "limit": 50,
    "offset": 100,
    "has_more": true
  }
}
```

## Error Responses

Errors return a consistent JSON structure:

```json theme={null}
{
  "error": {
    "code": "ASSET_NOT_FOUND",
    "message": "Asset not found",
    "details": {
      "asset_id": "snowflake.prod.warehouse.orders",
      "suggestion": "Check the qualified name format: source.database.schema.table"
    }
  }
}
```

### Error Codes

| Code               | HTTP Status | Description                           |
| ------------------ | ----------- | ------------------------------------- |
| `ASSET_NOT_FOUND`  | 404         | Asset doesn't exist or not accessible |
| `UNAUTHORIZED`     | 401         | Invalid or missing API key            |
| `FORBIDDEN`        | 403         | Valid key but insufficient scope      |
| `RATE_LIMITED`     | 429         | Too many requests                     |
| `VALIDATION_ERROR` | 400         | Invalid request parameters            |
| `INTERNAL_ERROR`   | 500         | Server error                          |

## Quick Start

<CodeGroup>
  ```python Python SDK theme={null}
  from anomalyarmor import Client

  # Initialize with API key
  client = Client(api_key="aa_live_xxx")

  # List assets
  assets = client.assets.list(source="snowflake", limit=10)
  for asset in assets:
      print(asset.qualified_name)

  # Check freshness (raises StalenessError if stale)
  client.freshness.require_fresh("snowflake.prod.warehouse.orders")
  ```

  ```bash cURL theme={null}
  # List assets
  curl -H "Authorization: Bearer aa_live_xxx" \
    "https://api.anomalyarmor.ai/api/v1/assets?limit=10"

  # Get freshness status
  curl -H "Authorization: Bearer aa_live_xxx" \
    "https://api.anomalyarmor.ai/api/v1/freshness?asset=snowflake.prod.warehouse.orders"
  ```

  ```bash CLI theme={null}
  # List assets
  armor assets list --source snowflake --limit 10

  # Check freshness (exits 1 if stale)
  armor freshness check snowflake.prod.warehouse.orders
  ```
</CodeGroup>

## Available Endpoints

<CardGroup cols={2}>
  <Card title="Assets" icon="database" href="/api/assets">
    List and retrieve data assets
  </Card>

  <Card title="Freshness" icon="clock" href="/api/freshness">
    Monitor and check data freshness
  </Card>

  <Card title="Schema" icon="table" href="/api/schema">
    Track schema changes and drift
  </Card>

  <Card title="Lineage" icon="diagram-project" href="/api/lineage">
    Explore data dependencies
  </Card>

  <Card title="Alerts" icon="bell" href="/api/alerts">
    Query alert history and status
  </Card>

  <Card title="Authentication" icon="key" href="/api/authentication">
    API key management
  </Card>
</CardGroup>

### Data Quality APIs

<CardGroup cols={3}>
  <Card title="Metrics" icon="chart-line" href="/api/metrics">
    Track row counts, null rates, and data trends
  </Card>

  <Card title="Validity" icon="check-circle" href="/api/validity">
    Enforce NOT NULL, UNIQUE, REGEX, and custom rules
  </Card>

  <Card title="Referential Checks" icon="link" href="/api/referential-checks">
    Verify foreign key relationships
  </Card>
</CardGroup>

## Next Steps

<CardGroup cols={3}>
  <Card title="SDK Quickstart" icon="python" href="/sdk/overview">
    Get started with the Python SDK
  </Card>

  <Card title="CLI Reference" icon="terminal" href="/cli/overview">
    Command-line interface guide
  </Card>

  <Card title="Airflow Integration" icon="wind" href="/integrations/airflow">
    Use with Apache Airflow
  </Card>
</CardGroup>

## Common Questions

### What is the base URL for the AnomalyArmor API?

All endpoints are served from `https://api.anomalyarmor.ai/api/v1`. Every request must include a Bearer token in the `Authorization` header. Point the Python or TypeScript SDK at a different `api_url` / `baseUrl` if you are targeting a staging environment.

### How do I handle rate limits and 429 responses?

Limits are per-API-key and vary by subscription tier, from 20 req/min on Free Trial up to 5,000 req/min on Enterprise. Every response includes `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and `X-RateLimit-Reset` headers, and 429s include a `Retry-After` header you should honor before retrying. The TypeScript SDK retries idempotent requests automatically; the Python SDK raises `RateLimitError` with a `retry_after` attribute.

### How does pagination work on list endpoints?

List endpoints use offset/limit pagination with `limit` (default 50, max 100) and `offset` query parameters. Responses include a `pagination` object with `total`, `limit`, `offset`, and `has_more` so you can loop until `has_more` is `false`. Prefer paging in batches of 100 to minimize request count against your rate limit.

### What error codes does the API return?

Errors come back as `{"error": {"code", "message", "details"}}`. Common codes include `ASSET_NOT_FOUND` (404), `UNAUTHORIZED` (401), `FORBIDDEN` (403), `RATE_LIMITED` (429), `VALIDATION_ERROR` (400), and `INTERNAL_ERROR` (500). The `details` object usually includes field names or suggestions you can surface in logs.

### Should I use the REST API directly or the SDK?

Use the SDK in application code: it handles auth, retries on 429, and typed responses for you. Hit the REST API directly from shell scripts, non-supported languages, or when you need a verb not yet wrapped by the ergonomic SDK surface. Both paths share the same `aa_live_*` Bearer token.
