Agoralia docs
Connect

Authentication

The Agoralia credential model — REST X-API-Key vs OAuth for MCP and the CLI, scopes, rate limits, and idempotency.

Authentication

Agoralia exposes three connect surfaces. They share one workspace and one permission model, but authenticate differently.

SurfaceCredentialHeaderBase
REST APIag_… API keyX-API-Key: ag_…https://api.agoralia.app/api/v1
MCPOAuth 2.1 (Bearer)Authorization: Bearer …https://api.agoralia.app/mcp
CLIOAuth Bearer (CLI token)Authorization: Bearer …https://api.agoralia.app

The REST API is available on all plans. Abuse is bounded by per-plan rate limits, not by a hard plan gate.

REST: X-API-Key

Create a key in Dashboard → API Keys. Keys start with the ag_ prefix and are shown once at creation — store it securely, you cannot retrieve it again.

Send it on every request in the X-API-Key header:

curl https://api.agoralia.app/api/v1/me \
  -H "X-API-Key: ag_your_key_here"

Each key is scoped to a workspace and carries a fixed set of scopes. A request missing the required scope returns 403 Missing scope: <scope>. Invalid, malformed (no ag_ prefix), or expired keys return 401.

OAuth: MCP and the CLI

MCP clients and the CLI authenticate with an OAuth 2.1 Bearer token instead of an ag_ key.

  • MCP uses OAuth 2.1 with Dynamic Client Registration (DCR). Your client performs the authorization flow on first connect; you approve a consent screen in the dashboard. See MCP.
  • CLI uses a long-lived CLI token you mint in the dashboard (Dashboard → API Keys → "CLI token") and store locally. See CLI.

MCP and the CLI hit the gated agent surface (/pages, /approvals, /actions, plus gated resource routes), not the /api/v1 REST namespace. Every call is gated server-side and tagged with the surface in the audit log.

Scopes

API keys carry an explicit list of scopes. A request is rejected with 403 if the key is missing the scope for that endpoint.

ScopeGrants
me:readRead workspace / account info
agents:readList and read agents
agents:writeCreate, update, publish agents
campaigns:readList and read campaigns
campaigns:writeCreate and update campaigns
campaigns:startLaunch / start campaigns
leads:readRead campaign leads
leads:writeAdd and update leads
calls:readRead calls, transcripts, recordings
calls:writePlace calls
results:readRead call results and analytics
numbers:readList phone numbers
numbers:writeLink BYO numbers, configure inbound, release numbers
billing:readRead billing and usage
compliance:readRead compliance status
compliance:writeManage DNC and compliance
sms:read / sms:writeRead / send SMS
webhooks:read / webhooks:writeRead / configure webhooks

See all scopes for the complete reference.

Grant a key only the scopes it needs. campaigns:start is deliberately separate from campaigns:write so a key can build campaigns without being able to launch them.

Rate limits

Limits are per-workspace and scale with your billing plan. Over-limit requests return HTTP 429 with a message telling you whether you hit the per-minute or per-day cap.

PlanPer minutePer day
Free / unknown301,000
Starter605,000
Professional12020,000
Business300100,000
Enterprise600500,000

When the limiter backend is unavailable, requests are allowed (fail-open) so legitimate traffic is never blocked by a limiter outage.

Idempotency

Mutating requests accept an Idempotency-Key header. Replaying the same key returns the stored response instead of performing the action again.

curl -X POST https://api.agoralia.app/api/v1/campaigns \
  -H "X-API-Key: ag_your_key_here" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: campaign-2026-06-17-001" \
  -d '{"name":"June outreach"}'

Reusing the same key with a different request body returns 409 Idempotency key reused with different request body.

Next