# auth.md — Zebra Authentication

Zebra's web tools and AI agent endpoints are **public and require no authentication**.

This document follows the agent-auth walkthrough structure. Because Zebra is a
zero-auth service, several steps resolve to "nothing to do" — they are kept, and
explained, so an agent can confirm that quickly instead of hunting for a login
flow that does not exist.

## Summary

| Resource | Auth required | Notes |
| --- | --- | --- |
| Website (`https://zebra.tg/`) | None | All tool pages are open. |
| Public HTTP API | None | See `/openapi.json` and `/api-docs.md`. |
| MCP server (`https://zebra.tg/api/mcp`) | None | Live JSON-RPC 2.0: `initialize`, `tools/list`, `tools/call`. |
| A2A endpoint (`https://zebra.tg/api/mcp`) | None | See `/.well-known/agent-card.json`. |
| Health check (`https://zebra.tg/api/health`) | None | Returns service status. |

## 1. Discover

Machine-readable descriptors, all served without credentials:

| Descriptor | URL |
| --- | --- |
| OpenAPI 3.1 spec | `https://zebra.tg/openapi.json` |
| API reference | `https://zebra.tg/api-docs.md` |
| Protected-resource metadata (RFC 9728) | `https://zebra.tg/.well-known/oauth-protected-resource` |
| API catalog (RFC 9727) | `https://zebra.tg/.well-known/api-catalog` |
| Agent resource directory | `https://zebra.tg/.well-known/ai-catalog.json` |
| A2A agent card | `https://zebra.tg/.well-known/agent-card.json` |
| MCP server card | `https://zebra.tg/.well-known/mcp/server-card.json` |
| Agent Skills index | `https://zebra.tg/.well-known/agent-skills/index.json` |

There is **no** `/.well-known/oauth-authorization-server` and **no**
`/.well-known/openid-configuration`, because there is no authorization server.
Their absence is intentional, not a misconfiguration.

## 2. Pick a method

There is exactly one method: **anonymous access**. No API keys, OAuth flows,
bearer tokens, mTLS, or signed requests are supported or required.

Accordingly, in `/.well-known/oauth-protected-resource` the fields
`authorization_servers`, `scopes_supported`, and `bearer_methods_supported` are
present but **empty arrays** — the resource is declared, and declared to need
nothing.

## 3. Register

**Nothing to register.** There is no developer portal, no client registration
endpoint, no application review, and no waitlist. Dynamic Client Registration
(RFC 7591) is not implemented because there is no client identity to issue.

Send your first request immediately:

```sh
curl https://zebra.tg/api/health
```

## 4. Claim a credential

**No credential exists to claim.** There is no key to generate, rotate, or
store. Any agent framework field for an API key should be left empty; do not
send an `Authorization` header — it is ignored.

The one header non-browser clients **do** need on `POST` requests is an origin
declaration, which is a CSRF speed-bump rather than a credential:

```
Origin: https://zebra.tg
```

It is a fixed public constant, identical for every caller. It authenticates
nothing and grants nothing.

## 5. Use the credential

Call the endpoint directly. A complete, working example:

```sh
curl -X POST 'https://zebra.tg/api/compress-pdf?tier=medium' \
  -H 'Origin: https://zebra.tg' \
  -F 'file=@input.pdf' \
  -o output.pdf
```

`GET` endpoints need no headers at all:

```sh
curl https://zebra.tg/api/usage/limits
```

Quotas for metered tools are tracked against an anonymous `zebra_anon` cookie
and the caller's IP. Persisting the cookie jar across calls keeps an agent on a
single quota identity rather than being treated as a new caller each time:

```sh
curl -c jar.txt -b jar.txt https://zebra.tg/api/usage/limits
```

Full endpoint documentation: <https://zebra.tg/api-docs.md>.

## 6. Errors

Auth-adjacent failures an agent should expect and handle:

| Status | Body | Meaning | What to do |
| --- | --- | --- | --- |
| `403` | `{"error":"forbidden origin"}` | The request sent no `Origin`/`Referer`, or a foreign one. | Resend with `Origin: https://zebra.tg`. This is **not** an auth failure — do not go looking for credentials. |
| `402` | `{"error":...}` | Premium-only tier requested, or the free allowance is exhausted. | Fall back to the free tier (e.g. `quality=standard`), or stop. Signing up will not help an agent — premium is tied to a human's purchase. |
| `429` | `{"error":"rate_limit",...}` | Per-IP or per-cookie rate limit hit. | Honour `Retry-After` and back off exponentially. |
| `401` | — | **Never returned.** No endpoint challenges for credentials. | If you receive one, you are not talking to Zebra. |

A `403` here never means "your token is invalid" — there are no tokens. It means
the origin header was absent or wrong.

## 7. Revocation

**Nothing to revoke.** With no credentials issued, there is no revocation
endpoint, no token introspection, and no logout for agent access. Access cannot
be withdrawn from an individual agent because no agent is individually
identified.

Two related controls do exist:

- **Rate limiting** is applied per IP and per anonymous cookie. Abuse results in
  temporary `429` responses, which lapse on their own — there is no permanent
  ban list to appeal.
- **Human accounts** (used only for premium purchases in the browser UI) can be
  deleted on request via <https://zebra.tg/contact/>. This is unrelated to agent
  access, which stays open.

## Details

- **No API keys, OAuth, or tokens** are needed to discover or call Zebra's
  agent-facing endpoints.
- **Rate limiting** applies to abuse-prone server endpoints (background removal,
  auto-enhance, PDF compression). Limits are enforced by IP and anonymous
  cookie, not by an authenticated identity. Exceeding a limit returns HTTP `429`
  with a `Retry-After` header.
- **Premium features** (higher batch limits, HD background removal) are tied to
  a user's in-app purchase and are not exposed through unauthenticated agent
  endpoints.
- **Most tools need no endpoint at all** — filters, crop, blur, grain, collage,
  image compression, and PDF merge run client-side in the browser.

## agent_auth

```json
{
  "agent_auth": {
    "registration_required": false,
    "identity_types_supported": [],
    "credential_types_supported": [],
    "revocation_supported": false,
    "protected_resource": "/.well-known/oauth-protected-resource",
    "openapi": "/openapi.json",
    "documentation": "/api-docs.md",
    "required_headers": {
      "Origin": "https://zebra.tg"
    },
    "notes": "All agent-facing endpoints are public. No registration, credentials, or tokens are required. POST requests must send a fixed public Origin header as a CSRF speed-bump; it is not a credential."
  }
}
```
