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

# Authentication

> Bearer tokens, API keys, scopes, and rate limiting.

Two auth methods are supported. Use **Bearer Tokens** for user-context operations; use **API Keys** for all automation, server-to-server, and long-running integrations.

<Tabs>
  <Tab title="Bearer Token">
    Issued on login. Carries full user-level permissions within the organization — suited for frontend apps and dashboard interactions.

    <CodeGroup>
      ```bash cURL theme={null}
      curl -X POST https://app.autoposting.ai/api-proxy/auth/login \
        -H "Content-Type: application/json" \
        -d '{"email": "you@example.com", "password": "your-password"}'
      # Response: { "data": { "token": "eyJhbGci..." } }
      ```

      ```typescript TypeScript theme={null}
      const { data } = await fetch("https://app.autoposting.ai/api-proxy/auth/login", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ email: "you@example.com", password: "your-password" }),
      }).then((r) => r.json());

      // Use data.token in subsequent requests
      ```
    </CodeGroup>

    <Note>
      Session tokens expire. For long-running server processes, use API keys instead.
    </Note>
  </Tab>

  <Tab title="API Key">
    Org-scoped keys with declared permission scopes. Accepted via `Authorization: Bearer` or `x-api-key` header — recommended for all programmatic access.

    <CodeGroup>
      ```bash cURL theme={null}
      # Create a key (requires active session token)
      curl -X POST https://app.autoposting.ai/api-proxy/api-keys \
        -H "Authorization: Bearer <session-token>" \
        -H "Content-Type: application/json" \
        -d '{"name": "prod-automation", "scopes": ["posts:write", "posts:read", "brands:read"]}'
      ```

      ```typescript TypeScript theme={null}
      const { data } = await fetch("https://app.autoposting.ai/api-proxy/api-keys", {
        method: "POST",
        headers: { Authorization: `Bearer ${sessionToken}`, "Content-Type": "application/json" },
        body: JSON.stringify({ name: "prod-automation", scopes: ["posts:write", "posts:read"] }),
      }).then((r) => r.json());

      console.log(data.key); // sk-social-your-key — store immediately, shown only once
      ```
    </CodeGroup>

    <Warning>
      The full key value is returned only once at creation. Store it in a secrets manager — if lost, revoke and create a new one.
    </Warning>

    Use the key on every request:

    ```bash theme={null}
    # Authorization header (recommended)
    curl https://app.autoposting.ai/api-proxy/posts -H "Authorization: Bearer sk-social-your-key"

    # x-api-key header (alternative)
    curl https://app.autoposting.ai/api-proxy/posts -H "x-api-key: sk-social-your-key"
    ```

    **SDK usage:**

    ```typescript theme={null}
    import { Autoposting } from '@autoposting.ai/sdk'
    const client = new Autoposting({ apiKey: 'sk-social-...' })
    ```
  </Tab>

  <Tab title="CLI Login">
    The Autoposting CLI supports a device code login flow — no API key required for interactive use.

    ```bash theme={null}
    ap auth login
    # Opens your browser to authorize the CLI.
    # Once approved, the session token is stored locally.
    ```

    <Note>
      CLI sessions use the same Bearer Token mechanism under the hood. For unattended scripts and CI/CD, use an API key instead.
    </Note>
  </Tab>
</Tabs>

## Permission Scopes

Requests outside granted scopes return `403 Forbidden`. Grant only what your integration needs.

| Scope             | Access                                                     |
| ----------------- | ---------------------------------------------------------- |
| `posts:read`      | List and retrieve posts, drafts, publish results           |
| `posts:write`     | Create, update, delete, publish, schedule, retry posts     |
| `brands:read`     | List brands and retrieve brand details                     |
| `brands:write`    | Create, update, delete, and reorder brands                 |
| `clips:read`      | List clip jobs, retrieve results and download URLs         |
| `clips:write`     | Upload videos, trigger scene detection and clip generation |
| `carousels:read`  | List and retrieve carousel drafts                          |
| `carousels:write` | Create, generate, refine, and publish carousels            |
| `kb:read`         | Search and read knowledge base documents                   |
| `kb:write`        | Upload, ingest, and delete knowledge base content          |
| `agents:read`     | List agents, view run history and outputs                  |
| `agents:write`    | Create, update, toggle, and run agents                     |
| `webhooks:read`   | List webhook endpoints                                     |
| `webhooks:write`  | Create, update, and delete webhook endpoints               |

## Rate Limiting

Limits are enforced per API key and per user session. Exceeding the limit returns `429 Too Many Requests`. Implement exponential backoff — start at 1 second, double on each retry, cap at 60 seconds.

| Header                  | Description                              |
| ----------------------- | ---------------------------------------- |
| `X-RateLimit-Limit`     | Maximum requests allowed in the window   |
| `X-RateLimit-Remaining` | Requests remaining in the current window |
| `X-RateLimit-Reset`     | Unix timestamp when the window resets    |
| `Retry-After`           | Seconds to wait before retrying          |

## Error Reference

| Status                  | Meaning                                          |
| ----------------------- | ------------------------------------------------ |
| `401 Unauthorized`      | Missing, invalid, or expired token / API key     |
| `402 Payment Required`  | Insufficient credits for the requested operation |
| `403 Forbidden`         | Valid credentials but insufficient scope         |
| `429 Too Many Requests` | Rate limit exceeded                              |

## Best Practices

<AccordionGroup>
  <Accordion title="Use API keys for all automation" icon="key">
    Never embed session tokens in scripts or CI/CD pipelines. Session tokens are user-bound and expire — API keys are designed for programmatic access and don't expire unless revoked.
  </Accordion>

  <Accordion title="Scope to minimum permissions" icon="shield-check">
    A key that only needs `posts:read` should not have `posts:write`. Reducing scope limits blast radius if a key is compromised.
  </Accordion>

  <Accordion title="Store keys in a secrets manager" icon="vault">
    Use environment variables, AWS Secrets Manager, 1Password Secrets Automation, or Doppler. Never commit a key to source control — even in a private repo.
  </Accordion>

  <Accordion title="Rotate keys on a schedule" icon="arrows-rotate">
    Revoke and recreate API keys periodically. Revoke immediately if a key is ever exposed — revocation is instant and permanent.
  </Accordion>
</AccordionGroup>

<CardGroup cols={2}>
  <Card title="Quickstart" icon="rocket" href="/quickstart">
    Create your first API key and publish a post in 5 minutes.
  </Card>

  <Card title="API Reference" icon="code" href="/api-reference/overview">
    Full endpoint reference with auth examples on every request.
  </Card>

  <Card title="API Keys endpoint" icon="key" href="/api-reference/overview">
    Create, list, update, and revoke keys programmatically.
  </Card>

  <Card title="MCP Server" icon="robot" href="/mcp/overview">
    Use Autoposting from Claude with automatic auth handling.
  </Card>
</CardGroup>
