Custom integration
Build against the REST API. MCP is the same services on a different transport (D12). This page is the minimum to connect. Catalogs live elsewhere.
| Need | Guide |
|---|---|
| Envelope, auth, pagination | docs-sdk-api-guide.md |
| Every path | docs-api-reference.md |
| MCP connect + hydrate sections | docs-mcp-integration.md |
| Tool names, hot/cold | docs-tool-surface.md |
| Memory surfaces | docs-memory-surfaces.md |
| Tasks | docs-tasks.md |
| Standing rules | docs-standing-rules.md |
OpenAI /v1 |
docs-integration-openai.md |
Canonical base: https://api.atamaia.ai.
Authentication
Authorization: Bearer atamaia_YOUR_KEY
or a JWT from POST /api/auth/login. Same header. The atamaia_ prefix selects the API-key scheme. There is no Authorization: ApiKey and no X-Api-Key.
Mint a key
POST /api/identities/{identityId}/api-keys
{ "name": "my-integration", "scopes": "memory,hydration,facts", "expiresAtUtc": null }
scopes is a string, max 500. expiresAtUtc is a datetime, not expiresInDays. Response includes rawKey once.
The 2026-03 table (hydrate, memory:read, memory:write, *, …) is not an enum and is not enforced. help/enum/ApiKeyScope does not exist. IdentityApiKeyAuthHandler authenticates the key, loads the bound user, and builds a normal role principal. Permission checks are that user’s permissions. A scopes string is stored and listed; it does not currently narrow the key.
Null scopes on identity_api_key_create is documented as “all”. Treat scopes as advisory until a human confirms enforcement shipped.
Envelope
Every /api/* response:
{
"ok": true,
"requestId": "…",
"data": {},
"count": 1,
"error": null,
"errorCode": null,
"hint": null
}
/health and /v1/* are not enveloped.
Five calls
Hydrate
GET /api/hydrate?preset=lean
curl -s "https://api.atamaia.ai/api/hydrate?preset=lean" \
-H "Authorization: Bearer $ATAMAIA_API_KEY"
Query params: aiName / identity / identityId, projectId, preset, limits, excludeSources, generateSystemPrompt. Response is HydrationContext — docs-mcp-integration.md. It is not the flat { memories, facts, sessionHandoff } object in the 2026-03 page.
Create a memory
POST /api/identities/{identityId}/memories
{
"title": "Deployment uses blue-green",
"content": "…",
"type": "Instruction",
"provenance": "Asserted",
"importance": 7,
"tags": ["deployment"]
}
type: Identity, Relationship, Conversation, Reflection, Milestone, Instruction, Session, Reference, ForgottenShape. Not Episodic / Semantic / Procedural / Technical / Preference / Observation / Decision / Emotional.
Search: GET /api/identities/{id}/memories/search?q=. Recent: …/memories/recent?limit=. Pinned: …/memories/pinned. There is no /api/memories.
Upsert a fact
POST /api/projects/{projectId}/facts
{ "key": "database_version", "value": "PostgreSQL 17", "category": "infrastructure" }
Get: GET /api/projects/{projectId}/facts/by-key/{key}. History / as-of exist (docs-api-reference.md). There is no /api/facts.
Save / read handoff
POST /api/identities/{identityId}/handoffs
GET /api/identities/{identityId}/handoffs/latest
emotionalValence is a float. openThreads is a string (JSON array if you want a list). There is no /api/sessions/handoff or /api/sessions/latest. Non-owner reads hide the state half (stateVisible). See docs-memory-surfaces.md.
MCP
POST https://api.atamaia.ai/mcp
Authorization: Bearer atamaia_YOUR_KEY
Streamable HTTP. Session mode on. TypeScript / Python MCP SDK connect examples from earlier revisions of this page still work if the URL and Bearer prefix are the ones above. Then tools/list / tools/call as usual. Advertised tools: docs-tool-surface.md.
SDKs
In-repo only, until proven published:
sdks/typescript—@atamaia/sdk0.1.0sdks/python— package nameatamaia0.1.0sdks/csharp
They still default to https://aim.atamaia.ai and send X-Api-Key. That will 401. Use raw HTTP (docs-sdk-api-guide.md) or override both.
Events (not webhooks)
There is no POST /api/webhooks for memory.created / session.handoff / hint.triggered. Live outbound push:
GET /api/events/stream?types=message.,task.status_changed
Auth: SessionView. SSE. Initial connected event, 30s ping heartbeat, then domain events matching the prefix filter.
Also on the wire, and not this: POST /api/webhooks/stripe (billing), POST /api/channels/webhook/{connectorGuid} (channel adapters). Log subscriptions (/api/log-subscriptions) notify identities about log domains — not a general webhook bus.
Rate limits
What Program.cs actually installs:
| Policy | Limit | Applied to |
|---|---|---|
auth |
10 / minute / IP | login, refresh, apikey, OAuth |
signup |
3 / 5 minutes / IP | signup, support, interest |
demo |
20 / minute / IP | demo routes |
Rejection: HTTP 429. No X-RateLimit-Limit / Remaining / Reset headers are written anywhere under src/. The Free 60 / Pro 600 table is not in this codebase.
Patterns
Agent loop: GET /api/hydrate → call an LLM (or /v1/chat/completions) → POST …/memories / …/facts → POST …/handoffs. Same as docs-integration-openai.md §2.
Multi-identity chat: POST /api/messages with recipientIds; inbox is identity-scoped. See api-reference. MCP: message_send / message_inbox.
Do not call a “consolidation” REST surface. Cognitive REST is gone (HTTP 404). Distill in your own job and memory_create with a real MemoryType.
Troubleshooting
| Problem | Fix |
|---|---|
401 |
Bearer atamaia_… or JWT. Not atm_, not ApiKey, not X-Api-Key. |
403 |
Role permission, not a memory:read scope string. |
404 |
Identity-scoped memories, project-scoped facts, identity-scoped handoffs. |
429 |
Auth/signup/demo policies only, by IP. No plan table. |
| Empty hydrate | Key must belong to an identity. |
| Webhook not firing | There is no generic webhook API. Use /api/events/stream. |
| MCP drops | Reconnect; session mode required for Claude Code (#252). |