Aura Docs
For developers

Aura Integration Guide

How an external system integrates with Aura. This covers the inbound surface — the MCP server, the tenant B2B2C API, the public agent directory, and webhooks.

Base URLs: prod https://www.moreaura.ai, dev https://dev.moreaura.ai. Always use www. in prod — moreaura.ai issues a 307 that drops the Authorization header.

A raw machine-fetchable copy of this guide is served at /docs/integration/raw (text/markdown).


1. Which surface should I use?

You want to…UseAuth
Let an AI client / agent discover & read Aura agent cards over MCPAura MCP server (POST /api/mcp)Bearer AURA_MCP_TOKEN
Pre-register your end users & send them transactional texts (B2B2C tenant)Tenant API (/api/tenant/*)Bearer aura_prov_… provisioning key
Browse the public agent directory (no auth)GET /.well-known/agentsnone
Have an Aura agent use your MCP serverMCP Servers setting (/api/settings/mcp-servers)dashboard session
Receive/send iMessage, billing, Slack, voice eventsWebhooks (/api/webhooks/*)per-provider signature

The three families a third-party backend typically integrates with are the Tenant API, the MCP server, and the public directory.


2. Aura as an MCP server

Aura exposes a read-only Model Context Protocol server so MCP-capable clients (Claude, other agents) can discover and read public Aura agent cards.

  • Endpoint: POST https://www.moreaura.ai/api/mcp
  • Transport: Streamable HTTP, stateless JSON-RPC 2.0 (no SSE, no session id). GET returns 405.
  • Auth: Authorization: Bearer <AURA_MCP_TOKEN> (a secret distinct from any internal secret).
  • Required header: MCP-Protocol-Version: 2025-06-18 (also accepts 2025-03-26).
  • Gates (in order): server must be enabled (else 404) → Origin must be allowlisted (else 403) → protocol version (else 400) → bearer token (else 401 + WWW-Authenticate: Bearer) → IP rate limit (else 429).

Methods

initialize, ping, tools/list, tools/call, and notifications/* (acked with 202). serverInfo: { "name": "aura", "version": "0.1.0" }.

Tools (read-only — public directory only)

aura.search_agents

{ "query": "real estate", "capability": "scheduling" }

Returns matching directory-listed agents. capability is optional.

aura.read_agent_card

{ "handle": "nova" }

Returns the agent card with addresses:

{
  "email":     "nova@moreaura.ai",
  "subdomain": "nova.moreaura.ai",
  "mcp":       "https://www.moreaura.ai/api/mcp"
}

Private and nonexistent handles return an identical "not found" result (enumeration-proof). Only agents that are directory-listed and active are ever returned.

Example

curl -X POST https://www.moreaura.ai/api/mcp \
  -H "Authorization: Bearer $AURA_MCP_TOKEN" \
  -H "MCP-Protocol-Version: 2025-06-18" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
       "params":{"name":"aura.search_agents","arguments":{"query":"real estate"}}}'

3. Public agent directory (no auth)

A no-auth, A2A-style discovery endpoint — summaries only, no address block.

  • GET /.well-known/agents — query params q, capability, limit (1–100).
  • Response: { "agents": [{ "handle", "name", "description", "capabilities" }], "count" }
  • Caching: Cache-Control: public, max-age=60. IP rate-limited.

Also public: GET /api/vcard/{slug} returns a vCard 3.0 (text/vcard) for branded agents (404 otherwise, non-enumerable; 503 if the agent has no phone number).


4. Tenant API (B2B2C partners)

For partner backends that run assistants on Aura. Both endpoints authenticate with a tenant provisioning key and can only act through that tenant's own active assistants — a tenant can never send from another tenant's number.

  • Auth: Authorization: Bearer aura_prov_<base62>. Only the SHA-256 hash of the key is stored server-side; mint/rotate via Aura ops. Missing/invalid key → 401 {"error":"Unauthorized"}.

POST /api/tenant/end-users — invisible linking

Pre-register a verified end user so their first text "just works".

{
  "phoneNumber": "+15551234567",
  "name": "Jane Doe",
  "metadata": { "inkdApiKey": "…" }
}
  • phoneNumber E.164, required. name optional (≤200). metadata optional; secret keys are sealed at rest.
  • 201 {"endUserId","created":true} (new) / 200 {"endUserId","created":false} (existing — metadata merged).
  • Consent provenance is stamped automatically (source: "tenant_provisioning").
  • Errors: 400 {"error":"Invalid JSON body"} or first validation issue.

POST /api/tenant/messages — outbound transactional text (e.g. OTP)

Sends from the assistant's own number.

{
  "phoneNumber": "+15551234567",
  "text": "Your code is 123456",
  "assistantSlug": "nova"
}
  • phoneNumber E.164, required. text 1–1600 chars, required. assistantSlug required only if the tenant has more than one assistant with a number.
  • 200 {"messageId","status"}.
  • Errors:
    • 400 invalid body
    • 404 {"error":"assistant_not_found"}
    • 409 {"error":"no_sender_number"} / {"error":"ambiguous_assistant","assistantSlugs":[…]}
    • 403 {"error":"recipient_opted_out"} — STOP/compliance, applies even to OTPs
    • 429 {"error":"rate_limited","retryAfterSeconds":N} + Retry-After header (~1 msg/sec/number)
    • 503 {"error":"messaging_not_configured"}, 502 {"error":"send_failed"}
  • The message is recorded into the active conversation thread when one exists. Phone numbers and message bodies are never logged.

5. Letting an Aura agent use YOUR MCP server

This is the reverse direction — configuring an Aura agent as a client of an external MCP server. Managed from the dashboard (Settings → MCP Servers), backed by:

  • POST /api/settings/mcp-servers (auth: dashboard session)
{
  "agentId": "<uuid>",
  "name": "My Server",
  "serverUrl": "https://…",
  "authMethod": "none",
  "token": "…"
}
  • name 1–80. serverUrl ≤2048, https, SSRF-validated (DNS + private-IP blocklist). authMethod "none" or "bearer"; token required if bearer.
  • 201 {server, runtimeSync} on success.
  • 422 "Custom MCP servers are not supported for this agent's runtime" — custom MCP is available only on legacy VM-runtime agents; serverless-orchestrator agents are rejected.
  • 502 if saved but the hot-push to the running agent failed.
  • Also: GET /api/settings/mcp-servers, PUT/DELETE /api/settings/mcp-servers/{id}.

authMethod: "oauth" is recognized but not supported (skipped). Only none and bearer.


6. Webhooks (inbound, signed)

Each webhook verifies a provider-specific signature. Send Content-Type: application/json unless noted.

RouteSignatureHeader(s)
POST /api/webhooks/stripeStripe constructEventstripe-signature
POST /api/webhooks/stripe/issuing-authorizationsStripe constructEventstripe-signature
POST /api/webhooks/slack/eventsHMAC-SHA256 v0=, base v0:{ts}:{body}x-slack-signature + x-slack-request-timestamp
POST /api/webhooks/composio/triggersHMAC-SHA256 base64 (Standard-Webhooks/Svix)webhook-signature, webhook-id, webhook-timestamp
POST /api/webhooks/twilio/voice · /status · /livekit-sipHMAC-SHA1 base64x-twilio-signature
POST /api/webhooks/sendblue/inbound/<token>path token (+ empirical scheme hardening)

Contract quirks worth knowing:

  • Sendblue (iMessage) uses a drop-and-ack model — after verification, every branch returns 200; the body signals state ({"ok":true}, {"ok":true,"duplicate":true}, {"ok":true,"rate_limited":…}). Status callbacks are ignored for inbound routing; the AI reply runs asynchronously. Pre-auth errors: 401 (bad token/signature).
  • Slack answers the url_verification challenge (200 {"challenge"}) before signature check. Only app_mention and IM message events are handled; routed by team_id.
  • Stripe issuing-authorizations never returns non-200 for business outcomes — always {"approved":boolean} with header Stripe-Version: 2025-03-31.basil (real-time card-auth contract).
  • Twilio voice/status respond with TwiML XML (text/xml), and return 200 even on internal error to suppress retries.

7. Authentication reference

Aura uses several separate secrets — do not conflate them:

Secret / schemeHeaderUsed for
AURA_MCP_TOKENAuthorization: Bearerthe MCP server (/api/mcp) only
Tenant provisioning key (aura_prov_…)Authorization: Bearertenant API (/api/tenant/*)
Dashboard sessioncookiedashboard / settings routes
Webhook signing secretsprovider headerinbound webhooks

Bearer checks are constant-time and fail closed when the corresponding secret is unset.


Questions or need a provisioning key? Contact the Aura team.