Get started
Base URL
Every request goes to https://api.kirora.io under the /v1 prefix.
Common tasks
| To | Call |
|---|---|
| Create or update a person from your app | POST /v1/contacts/identify |
| Record what someone did, so journeys can react | POST /v1/events/track |
| Send a receipt, password reset or alert | POST /v1/transactional/messages |
| Send a push notification to one person | POST /v1/push/messages |
| Register a device for push | POST /v1/contacts/{id}/installations |
| Send a campaign built in the dashboard | POST /v1/campaigns/{id}/send |
| Send a campaign to people you name, each with their own data | POST /v1/campaigns/{id}/trigger |
| Hear when a message is delivered, opened or bounces | POST /v1/webhooks |
| Export what was sent, as CSV | POST /v1/messages/exports |
| Erase a person and their history | POST /v1/contacts/erase |
Authentication
Send a scoped API key as a bearer token. Each endpoint page names the scope it needs; a key without it gets a403. Keys come in two kinds: integration keys, and agent keys for AI tools, which can read and draft but never send. See authentication.
curl https://api.kirora.io/v1/me \
-H "Authorization: Bearer $KIRORA_API_KEY"const response = await fetch('https://api.kirora.io/v1/me', {
method: 'GET',
headers: {
Authorization: `Bearer ${process.env.KIRORA_API_KEY}`,
},
});
const { data } = await response.json();import os
import requests
response = requests.get(
"https://api.kirora.io/v1/me",
headers={
"Authorization": f"Bearer {os.environ['KIRORA_API_KEY']}",
},
)
data = response.json()["data"]package main
import (
"encoding/json"
"net/http"
"os"
)
func main() {
req, err := http.NewRequest("GET", "https://api.kirora.io/v1/me", nil)
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIRORA_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
var out struct {
Data json.RawMessage `json:"data"`
}
if err := json.NewDecoder(res.Body).Decode(&out); err != nil {
panic(err)
}
}Responses
Requests and responses are JSON. Successful responses carry the payload under data, with metawhere there is more to say, such as the next page’s cursor. Errors replace data with error, whosecode is stable and safe to branch on. Lists are cursor-paginated (see pagination), and sends and tracked events take an Idempotency-Key (see idempotency).
Status codes
2xx means it worked; each endpoint page says which one it returns. Every endpoint can also return the errors below, so they are listed here once rather than on every page.
| Status | Meaning |
|---|---|
400 | The request was malformed or failed validation. error.code says which. |
401 | The API key is missing, malformed, revoked, or expired. |
403 | The key is valid but lacks the required scope, or is an agent key attempting an operation agent keys may not perform. |
404 | No such resource in this organization. A resource owned by another organization also returns 404, never 403. |
409 | The request conflicts with current state — a duplicate unique value, or a resource whose status does not allow this operation. |
429 | Rate limit exceeded. The Retry-After header says how long to wait. |
500 | An unexpected server error. Retrying an idempotent request is safe. |
503 | A dependency is temporarily unavailable. Retry with backoff. |
All 44 error codes
BAD_REQUESTALREADY_EXISTSCONFLICTIN_USEFORBIDDENINTERNAL_ERRORNOT_FOUNDRATE_LIMITEDREVISION_CONFLICTSERVICE_UNAVAILABLEUNAUTHORIZEDVALIDATION_ERRORAPI_KEY_IP_NOT_ALLOWEDAGENT_CONFIRMATION_REQUIREDEMBED_ORIGIN_NOT_ALLOWEDWORKSPACE_SUSPENDEDWORKSPACE_DELETION_PENDINGCONTACT_SEND_IN_PROGRESSEXPORT_UNAVAILABLENOTHING_TO_EXPORTEVENT_NAME_LIMIT_REACHEDPLAN_LIMIT_REACHEDPLAN_FEATURE_UNAVAILABLECAMPAIGN_AUDIENCE_CONFLICTEMPTY_AUDIENCEINVALID_CAMPAIGN_CONTENTDRAFT_INCOMPLETEINVALID_SCHEDULEUNSUPPORTED_CHANNELPOSTAL_ADDRESS_MISSINGCONSENT_MISSINGSUPPRESSEDSIGNUP_BLOCKEDINVALID_SENDER_ADDRESSSENDING_DOMAIN_DMARC_MISSINGSENDING_DOMAIN_IDENTITY_CONFLICTSENDING_DOMAIN_UNVERIFIEDIDEMPOTENCY_KEY_REUSEDCONTENT_NOT_RETAINEDRECIPIENT_EMAIL_MISSINGTEMPLATE_NOT_PUBLISHEDTEMPLATE_ENVELOPE_INCOMPLETEPUSH_APP_NOT_READYPUSH_DESTINATION_MISSING
What each means, and which are worth retrying: errors.
Server libraries
Every endpoint page shows its request in cURL, Node.js, Python and Go. Typed server libraries, the React builders and the CLI are listed under SDKs, with their release status. Until a library for your language is published, call the API directly.