---
name: chatia
description: Agent Factory ("Chatia") — freelancer-first SaaS to build, publish, and embed AI agents in websites and WhatsApp, with user-level billing, multi-tenant clients, and a signed webhook bus.
version: 0.1
---

# Chatia · Skill for AI agents

Use this file to let Claude Code, Codex, Cursor, GPT agents and similar tools
operate Chatia from the API.

## What is Chatia

Chatia spins up AI agents that freelancers deploy to their own clients in
minutes. Every agent gets:

- A **webchat** at `/{public_slug}` and an **orbe widget** (`/widget.js`) for
  any website.
- A **WhatsApp connection** (Kapso BYOK) — optional.
- **Tools**: capture_lead, schedule_appointment, send_whatsapp_handoff,
  http_request, plus anything the agent-builder wires up.
- **Usage-based billing** via Polar (metered events per message,
  $0.010 managed / $0.004 BYOK, plus paid plans Starter/Pro/Studio/Agency).
- **Per-conversation human takeover** — flip `ai_paused=true` and reply as
  operator; the AI pauses for that thread.

## Base URL

All API calls go to the backend base URL, which is configured per environment:

- Local dev: `http://localhost:8000`
- Production: whatever you put in `NEXT_PUBLIC_API_URL` / `BACKEND_URL`.

**Do not hardcode** domains. Use the env var.

## Authentication

Two kinds of bearer tokens:

1. **User JWT** — emitted by `POST /api/auth/login`. Used by the dashboard
   app. Scope: the logged-in user's resources.
2. **Developer API key** — create one at `/dashboard/developers`. Scope: the
   user's agents + events ingestion. Prefix is `chatia_…`.

Both go in the `Authorization: Bearer <token>` header.

## Core API

### Agents

| Verb   | Path                                  | Notes                                                |
| ------ | ------------------------------------- | ---------------------------------------------------- |
| GET    | `/api/agents`                         | Your agents (paginated summary).                     |
| GET    | `/api/agents/{id}`                    | Full detail with tools.                              |
| PATCH  | `/api/agents/{id}`                    | Update identity, model, API keys, Kapso config.      |
| POST   | `/api/agents/{id}/publish`            | Publish and mint a `public_slug`.                    |
| POST   | `/api/agents/{id}/tools`              | Attach a builtin tool.                               |
| DELETE | `/api/agents/{id}`                    | Destructive — body `{ confirmation: "<agent name>" }`. |

### Builder (create agents by chat)

| Verb | Path                   | Notes                                      |
| ---- | ---------------------- | ------------------------------------------ |
| POST | `/api/builder/stream`  | SSE. Body: `{ message, images[], thread_id }`. |

Events emitted: `thread`, `plan_created`, `plan_step_updated`, `tool_called`,
`tool_output`, `external_action`, `text_delta`, `done`, `error`. The model is
`gpt-5.4`. Plans must use descriptive task names (not "Paso 1").

### Public webchat (no auth)

| Verb | Path                                            |
| ---- | ----------------------------------------------- |
| GET  | `/api/public/agents/{slug}`                     |
| POST | `/api/public/agents/{slug}/chat`                |
| POST | `/api/public/agents/{slug}/leads`               |

Chat body: `{ message, history, conversation_id?, visitor_id? }`.
Response: `{ reply, conversation_id, key_source, free_messages_remaining, human_takeover? }`.

### Conversations + human takeover

| Verb | Path                                                                               |
| ---- | ---------------------------------------------------------------------------------- |
| GET  | `/api/clients/me/agents/{id}/conversations`                                        |
| GET  | `/api/clients/me/agents/{id}/conversations/{cid}`                                  |
| POST | `/api/clients/me/agents/{id}/conversations/{cid}/takeover` · body `{ paused: bool }` |
| POST | `/api/clients/me/agents/{id}/conversations/{cid}/messages` · body `{ content }`    |
| GET  | `/api/clients/me/agents/{id}/leads`                                                |

Owners and clients (sub-users with a grant) can read these; the backend gates
by `ClientAgentGrant.scopes` (`messages` / `leads`).

### Billing

| Verb | Path                              | Notes                                              |
| ---- | --------------------------------- | -------------------------------------------------- |
| GET  | `/api/billing/plans`              | Public. Returns all plans + rates + seat price.    |
| GET  | `/api/billing/account`            | Current user's plan, usage, PM, agents used/limit. |
| POST | `/api/billing/checkout-session`   | `{ plan_slug }` → `{ url }` for PolarEmbedCheckout. |
| POST | `/api/billing/portal-session`     | → `{ url }` to open Polar Customer Portal.         |

### Developers

| Verb | Path                           |
| ---- | ------------------------------ |
| GET  | `/api/developers/overview`     |
| POST | `/api/developers/api-keys`     |
| POST | `/api/developers/webhooks`     |
| POST | `/api/developers/webhooks/{id}/test` |
| GET  | `/api/developers/agents`       |
| POST | `/api/developers/agents`       |
| POST | `/api/developers/events`       |

### Clients (sub-users of an owner)

| Verb | Path                                              |
| ---- | ------------------------------------------------- |
| GET  | `/api/clients`                                    |
| POST | `/api/clients`                                    |
| DELETE | `/api/clients/{id}`                             |
| POST | `/api/clients/{id}/grants`                        |
| DELETE | `/api/clients/{id}/grants/{agent_id}`           |
| GET  | `/api/clients/me/agents`                          |

### Admin (superadmin only)

| Verb  | Path                                 |
| ----- | ------------------------------------ |
| GET   | `/api/admin/metrics`                 |
| GET   | `/api/admin/users`                   |
| GET   | `/api/admin/users/{id}`              |
| PATCH | `/api/admin/users/{id}/status`       |
| POST  | `/api/admin/users/{id}/impersonate`  |
| POST  | `/api/admin/billing/report-usage`    |
| GET   | `/api/admin/billing/config`          |

## Events & webhooks

Outbound webhooks (HMAC-SHA256 signed, 5 retries):

- `agent.created`, `agent.published`
- `agent.message.created`, `agent.reply.created`
- `agent.lead.captured`
- `agent.tool.called`
- `agent.handoff.requested`, `conversation.closed`

Signing: `hmacSha256(webhookSecret, timestamp + "." + rawBody)`.
Headers: `x-chatia-signature`, `x-chatia-timestamp`, `x-chatia-event`, `x-chatia-event-id`.

Metered billing events are emitted internally (`name="ai_message"`,
`metadata.key_source="managed"|"byok"`) and reported in batch to Polar.

## Data model quick reference

- `User(role: owner | client | superadmin, parent_user_id?)`
- `Agent(owner_id, name, system_prompt, provider, model, config{kapso, ai}, public_slug, is_published)`
- `AgentTool(agent_id, name, schema, is_active)`
- `Conversation(agent_id, owner_id, visitor_id, channel, ai_paused, message_count)`
- `ConversationMessage(conversation_id, role: user|assistant|system|tool, content, meta)`
- `Lead(agent_id, owner_id, conversation_id?, name, email, phone, interest, source, status)`
- `BillingAccount(owner_id, plan, polar_customer_id, polar_subscription_id, has_payment_method, payg_enabled, messages_used_current_period, messages_used_managed, messages_used_byok)`
- `UsageEvent(owner_id, agent_id?, event_type, key_source, quantity, unit_cost_cents, reported_at)`
- `ClientAgentGrant(client_user_id, agent_id, scopes)`
- `DeveloperApiKey`, `WebhookEndpoint`, `WebhookDelivery`

## Quickstart as an AI agent

```bash
# 1) Issue a developer API key (via dashboard once, or via endpoint)
export CHATIA_API_KEY=chatia_...
export CHATIA_API=http://localhost:8000   # or your prod base URL

# 2) Create an agent
curl -X POST $CHATIA_API/api/developers/agents \
  -H "Authorization: Bearer $CHATIA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Soporte",
    "system_prompt": "Respondé FAQ, capturá datos si falta contexto.",
    "tools": ["capture_lead", "http_request"],
    "publish": true
  }'

# 3) Register a webhook
curl -X POST $CHATIA_API/api/developers/webhooks \
  -H "Authorization: Bearer $CHATIA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "crm", "url": "https://tu-crm.com/chatia/webhook" }'

# 4) Embed the widget
<script src="$CHATIA_API/widget.js"
  data-agent="<slug>"
  data-position="right"
  data-accent="#10b981"
  async></script>
```

## Pricing model (relevant for flows that trigger checkouts)

- **Free** — 50 msgs trial, 1 agente, sin tarjeta.
- **Pay-as-you-go** — activa cuando el user guarda tarjeta. Cobra metered.
- **Starter $5** · 2 agentes · 1k msgs.
- **Pro $12** · 4 agentes · 5k msgs.
- **Studio $29** · 6 agentes · 20k msgs.
- **Agency $59** · 15 agentes · 60k msgs.
- **Overage**: $0.010/msg (API nuestra) · $0.004/msg (BYOK).
- **Extra seat**: $5/mes cualquier plan pago.

## Safety & conventions

- Every destructive call needs explicit confirmation. `DELETE /api/agents/{id}`
  requires the user to type the exact agent name.
- Webchat never emits the `{ "reply": "..." }` before the message is persisted.
- The builder prompt forbids "Paso 1", "Paso 2". Use task names.
- `free_messages_remaining` is **per user**, not per agent.
- Do not redirect payments. Use `PolarEmbedCheckout.create(url, { theme: "dark" })`
  inline.

## When integrating with another AI agent platform

Read this file first. Then:

1. Ask for a `CHATIA_API_KEY` scoped to a single user.
2. Use only the endpoints listed above — no private routes.
3. Surface Chatia's webchat or widget as a resource the agent can embed or trigger.
4. Respect quotas: `/api/billing/account` tells you how close the user is to
   their agent/message limit.
