Public API
Use Ogma's key-authenticated HTTP API to build integrations and support apps — legacy ticket panels, CRMs, workflow bots, and custom dashboards.
API access is subject to the Developer Terms of Service, including the API access section and Discord's developer terms and policies.
Create an API key
- Open your server in the Ogma dashboard.
- Go to Settings → API keys.
- Select Create key, enter a descriptive name, and pick exactly the scopes the integration needs.
- Copy the key immediately and store it in your integration's secret manager. Ogma does not show the secret again.
Each key carries its own configurable set of scopes — there are no fixed roles, and you can change a key's scopes at any time without rotating it:
| Scope | Grants |
|---|---|
tickets:open | Open tickets |
tickets:read | List and read tickets, queue, tags, messages, transcripts |
tickets:write | Reply, reopen, escalate, claim/unclaim, tag |
tickets:close | Close tickets |
guild:read | Guild info, staff list, usage, macros |
webhooks:manage | Manage webhook subscriptions |
knowledge:read | Knowledge Q&A, list and read knowledge sources |
knowledge:write | Create, replace, and delete knowledge sources |
analytics:read | Insights, per-staff metrics, and CSAT |
Authentication
Authorization: Bearer ogma_<keyId>_<secret>curl https://api.ogma.gg/api/v1/me \
--header "Authorization: Bearer $OGMA_API_KEY"Tickets
| Method | Path | Scope |
|---|---|---|
GET | /api/v1/tickets | tickets:read |
GET | /api/v1/tickets/queue | tickets:read |
GET | /api/v1/tickets/tags | tickets:read |
GET | /api/v1/tickets/:ticketId | tickets:read |
GET | /api/v1/tickets/:ticketId/messages | tickets:read |
GET | /api/v1/tickets/:ticketId/transcript | tickets:read |
POST | /api/v1/tickets | tickets:open |
POST | /api/v1/tickets/:ticketId/messages | tickets:write |
POST | /api/v1/tickets/:ticketId/close | tickets:close |
POST | /api/v1/tickets/:ticketId/reopen | tickets:write |
POST | /api/v1/tickets/:ticketId/escalate | tickets:write |
POST | /api/v1/tickets/:ticketId/claim | tickets:write |
POST | /api/v1/tickets/:ticketId/unclaim | tickets:write |
PATCH | /api/v1/tickets/:ticketId/tags | tickets:write |
Open a ticket
curl https://api.ogma.gg/api/v1/tickets \
--request POST \
--header "Authorization: Bearer $OGMA_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"ticketTypeId": "customer_support",
"discordUserId": "189912345678901248",
"subject": "Billing help",
"description": "I cannot update my payment method."
}'Queue
curl "https://api.ogma.gg/api/v1/tickets/queue?filter=unclaimed" \
--header "Authorization: Bearer $OGMA_API_KEY"Filters: all, unclaimed, escalated, awaiting_staff, awaiting_customer, mine (requires assigneeDiscordId).
Claim / reply / close
# Claim (actorDiscordId required — must be staff)
curl https://api.ogma.gg/api/v1/tickets/$TICKET_ID/claim \
--request POST \
--header "Authorization: Bearer $OGMA_API_KEY" \
--header "Content-Type: application/json" \
--data '{ "actorDiscordId": "189912345678901248" }'
# Reply
curl https://api.ogma.gg/api/v1/tickets/$TICKET_ID/messages \
--request POST \
--header "Authorization: Bearer $OGMA_API_KEY" \
--header "Content-Type: application/json" \
--data '{ "content": "Looking into this now.", "actorDiscordId": "189912345678901248" }'
# Close
curl https://api.ogma.gg/api/v1/tickets/$TICKET_ID/close \
--request POST \
--header "Authorization: Bearer $OGMA_API_KEY" \
--header "Content-Type: application/json" \
--data '{ "closeReason": "resolved" }'Guild
| Method | Path | Scope |
|---|---|---|
GET | /api/v1/guild | guild:read |
GET | /api/v1/guild/staff | guild:read |
GET | /api/v1/guild/usage | guild:read |
GET | /api/v1/macros | guild:read |
GET /api/v1/guild returns enabled public ticket types. GET /api/v1/guild/staff lists Discord members with staff roles.
Webhooks
Requires a plan that includes webhooks (Plus/Enterprise) and the webhooks:manage scope.
| Method | Path |
|---|---|
GET | /api/v1/webhooks |
POST | /api/v1/webhooks |
PATCH | /api/v1/webhooks/:id |
DELETE | /api/v1/webhooks/:id |
curl https://api.ogma.gg/api/v1/webhooks \
--request POST \
--header "Authorization: Bearer $OGMA_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"name": "CRM",
"url": "https://example.com/ogma-hooks",
"secret": "your-hmac-secret",
"events": ["ticket.opened", "ticket.closed", "ticket.escalated"]
}'Events: ticket.opened, ticket.escalated, ticket.closed, csat.negative, sla.breach.
Delivery body:
{
"event": "ticket.opened",
"guildId": "…",
"occurredAt": "2026-07-20T12:00:00.000Z",
"payload": {}
}When a secret is configured, Ogma sends X-Ogma-Signature: sha256=<hex> — HMAC-SHA256 of the raw request body.
Knowledge
curl https://api.ogma.gg/api/v1/knowledge/ask \
--request POST \
--header "Authorization: Bearer $OGMA_API_KEY" \
--header "Content-Type: application/json" \
--data '{ "question": "How do I reset my password?" }'Requires knowledge:read. Returns { question, answer, shouldAnswer, confidence, reasoning }.
Manage the library itself to keep Ogma's knowledge in step with your own docs:
| Method | Path | Scope |
|---|---|---|
GET | /api/v1/knowledge | knowledge:read |
GET | /api/v1/knowledge/{documentKey} | knowledge:read |
POST | /api/v1/knowledge | knowledge:write |
PATCH | /api/v1/knowledge/{documentKey} | knowledge:write |
DELETE | /api/v1/knowledge/{documentKey} | knowledge:write |
Creating or replacing a source chunks and embeds the content, so it is searchable as soon as the request returns. Deleting removes the chunks along with the source's sync configuration and pin.
Analytics
| Method | Path | Scope |
|---|---|---|
GET | /api/v1/insights?days=30 | analytics:read |
GET | /api/v1/insights/staff?days=30 | analytics:read |
GET | /api/v1/csat?days=30 | analytics:read |
days is clamped to the window your plan allows, and each response reports the days actually used — so a request for 90 days on a plan capped at 30 returns 30 rather than failing.
Idempotent writes
Send an Idempotency-Key header on POST and PATCH requests to make retries safe:
curl https://api.ogma.gg/api/v1/tickets \
--request POST \
--header "Authorization: Bearer $OGMA_API_KEY" \
--header "Idempotency-Key: $(uuidgen)" \
--header "Content-Type: application/json" \
--data '{ "ticketTypeId": "support", "discordUserId": "…", "subject": "…" }'Retrying with the same key returns the original response and an Idempotent-Replay: true header instead of opening a second ticket. Keys are scoped to your API key, must be 8–255 characters, and stay replayable for 24 hours.
| Situation | Response |
|---|---|
| Same key, same body, original finished | The original response, with Idempotent-Replay: true |
| Same key, same body, original still running | 409 idempotency_in_flight |
| Same key, different body | 422 idempotency_key_reuse |
Original returned 5xx | Key released — your retry runs as a fresh request |
Errors
| Status | Codes | Meaning |
|---|---|---|
400 | invalid_body, invalid_query, invalid_ticket_id, invalid_idempotency_key | Bad request |
401 | unauthorized | Missing/invalid/revoked/expired key |
402 | plan_required | Feature not on current plan |
403 | missing_scope, actor_not_staff, forbidden | Not allowed |
404 | ticket_not_found, guild_not_found, webhook_not_found, document_not_found, … | Missing resource |
409 | ticket_conflict, max_open, categories_full, idempotency_in_flight | State conflict |
422 | idempotency_key_reuse | Idempotency key reused with a different body |
429 | rate_limited | Rate limit exceeded |
503 | bot_not_in_guild, message_failed, … | Discord unavailable |
Each key is limited to 60 requests per minute. Ticket opens are limited to 240 per hour per server. Knowledge ask also uses the guild AI completion limit.
Every response carries your current budget, so you can pace requests before you hit 429:
| Header | Meaning |
|---|---|
X-RateLimit-Limit | Requests allowed in the window |
X-RateLimit-Remaining | Requests left after this one |
X-RateLimit-Reset | Unix seconds when a slot frees up |
A 429 also returns Retry-After in seconds.
Building an app
- Create a key with the ticket scopes plus
guild:read,knowledge:read, andwebhooks:manage. Addknowledge:writeto sync your own docs in, andanalytics:readto pull reporting. - Register webhooks for ticket lifecycle events.
- Poll or push into
GET /api/v1/tickets/queuefor the inbox. - Use claim / messages / close for staff actions;
GET /api/v1/guild/stafffor assignee pickers. - Optionally expose
POST /api/v1/knowledge/askfor a docs assistant.
