API reference

Account API

Self-serve control surface. Dashboard/admin credential — never ship it in a product build.

Credential: as_ account session · scheme as_ account session

11 operations · 11 captured against the live API.

Every example below is a real exchange recorded against a throwaway tenant, then redacted — not a shape transcribed from a schema. Ids and timestamps are stable fixtures so the same request always reads the same way. Back to the full index →

Account #

POST /v1/account/signup #

Create an account and its tenant

signup captured live

Request

curl -X POST https://api.ollacore.com/v1/account/signup \
  -H "Content-Type: application/json" \
  -d '{"email":"[email protected]","password":"<redacted>"}'
{
  "email": "[email protected]",
  "password": "<redacted>"
}
ParameterTypeDescription
X-Request-Id header string Your own id for this request. It is returned in the response's X-Request-Id header and attached to every log line kept for the request, so quote it when you contact support. Use printable ASCII. Without it, the server assigns a UUID.

Request fields

FieldTypeDescription
email required string (email) Your email address; it becomes the login. Stored lowercased. Not verified: there is no email step.
password required string min length 12 · max length 256 12–256 characters. Stored only as an argon2 hash.

Response · 200

{
  "tenant_id": "acct_fac91b282191cc02dd29912c8db43f1c",
  "session_token": "as_EXAMPLE_SESSION",
  "expires_at": "2026-02-14T09:30:00Z"
}
Response fields (3)
FieldTypeDescription
tenant_id required string The account's auto-provisioned tenant.
session_token required string Opaque bearer (as_...), shown once.
expires_at required string (date-time) When this session stops working: 30 days after it was issued. Log in again for a new one.
Errors · 409
StatusWhen
409email already registered
POST /v1/account/login #

Log in

login captured live

Request

curl -X POST https://api.ollacore.com/v1/account/login \
  -H "Content-Type: application/json" \
  -d '{"email":"[email protected]","password":"<redacted>"}'
{
  "email": "[email protected]",
  "password": "<redacted>"
}
ParameterTypeDescription
X-Request-Id header string Your own id for this request. It is returned in the response's X-Request-Id header and attached to every log line kept for the request, so quote it when you contact support. Use printable ASCII. Without it, the server assigns a UUID.

Request fields

FieldTypeDescription
email required string (email) The email you signed up with.
password required string Your password.

Response · 200

{
  "tenant_id": "acct_fac91b282191cc02dd29912c8db43f1c",
  "session_token": "as_EXAMPLE_SESSION",
  "expires_at": "2026-02-14T09:30:01Z"
}
Response fields (3)
FieldTypeDescription
tenant_id required string The account's auto-provisioned tenant.
session_token required string Opaque bearer (as_...), shown once.
expires_at required string (date-time) When this session stops working: 30 days after it was issued. Log in again for a new one.
Errors · 401
StatusWhen
401Missing, expired or invalid credentials
POST /v1/account/logout #

Invalidate the session

logout captured live

Request

curl -X POST https://api.ollacore.com/v1/account/logout \
  -H "Authorization: Bearer as_…" \
  -H "Content-Type: application/json" \
  -d '{}'
{}
ParameterTypeDescription
X-Request-Id header string Your own id for this request. It is returned in the response's X-Request-Id header and attached to every log line kept for the request, so quote it when you contact support. Use printable ASCII. Without it, the server assigns a UUID.

Response · 200

{
  "logged_out": true
}
Response fields (1)
FieldTypeDescription
logged_out boolean True when this call removed the session. False only if a concurrent logout removed it first; either way the session no longer works.
Errors · 401
StatusWhen
401Missing, expired or invalid credentials

API keys #

GET /v1/account/api-keys #

List keys

listKeys captured live

Request

curl -X GET https://api.ollacore.com/v1/account/api-keys \
  -H "Authorization: Bearer as_…"
ParameterTypeDescription
X-Request-Id header string Your own id for this request. It is returned in the response's X-Request-Id header and attached to every log line kept for the request, so quote it when you contact support. Use printable ASCII. Without it, the server assigns a UUID.

Response · 200

{
  "api_keys": [
    {
      "created_at": "2026-01-15T09:30:01Z",
      "environment": "live",
      "expires_at": null,
      "id": "key-id-main",
      "last_used_at": null,
      "name": "docs-example-key",
      "plan": "default",
      "revoked_at": null,
      "scopes": [
        "rooms:read",
        "rooms:write",
        "members:write",
        "tokens:mint",
        "messages:write",
        "webhooks:manage",
        "usage:read",
        "rooms:delete",
        "data:erase"
      ]
    }
  ]
}
Response fields (1)
FieldTypeDescription
api_keys array of object The account's keys, without secrets.
Errors · 401
StatusWhen
401Missing, expired or invalid credentials
POST /v1/account/api-keys #

Create a key (secret shown once)

createKey captured live

Request

curl -X POST https://api.ollacore.com/v1/account/api-keys \
  -H "Authorization: Bearer as_…" \
  -H "Content-Type: application/json" \
  -d '{"name":"docs-example-key","environment":"live","scopes":["rooms:read","rooms:write","members:write","tokens:mint","messages:write","webhooks:manage","usage:read","rooms:delete","data:erase"]}'
{
  "name": "docs-example-key",
  "environment": "live",
  "scopes": [
    "rooms:read",
    "rooms:write",
    "members:write",
    "tokens:mint",
    "messages:write",
    "webhooks:manage",
    "usage:read",
    "rooms:delete",
    "data:erase"
  ]
}
ParameterTypeDescription
X-Request-Id header string Your own id for this request. It is returned in the response's X-Request-Id header and attached to every log line kept for the request, so quote it when you contact support. Use printable ASCII. Without it, the server assigns a UUID.

Request fields

FieldTypeDescription
name string Optional label for the key, for your own records.
environment required one of: live, test live or test. A test key works in its own data namespace and never sees live data.
scopes array of one of: rooms:read, rooms:write, members:write, tokens:mint, messages:write, webhooks:manage, usage:read, rooms:delete, data:erase Scopes to grant. Omit for the default set: rooms:read, rooms:write, members:write, tokens:mint, messages:write. usage:read, webhooks:manage, rooms:delete and data:erase must be asked for.

Response · 200

{
  "key_id": "key-id-main",
  "api_key": "ak_live_EXAMPLE.NOT_A_REAL_KEY",
  "environment": "live",
  "scopes": [
    "rooms:read",
    "rooms:write",
    "members:write",
    "tokens:mint",
    "messages:write",
    "webhooks:manage",
    "usage:read",
    "rooms:delete",
    "data:erase"
  ]
}
Response fields (4)
FieldTypeDescription
key_id required string The key's public id (ak_live_… or ak_test_…). Use it to rotate or revoke the key; it is not a credential.
api_key required string Full ak_<env>_<id>.<secret>, shown once.
environment required one of: live, test live or test. A test key sees only test data.
scopes required array of one of: rooms:read, rooms:write, members:write, tokens:mint, messages:write, webhooks:manage, usage:read, rooms:delete, data:erase What the key may do. A call outside these scopes is refused with 403 when it is made.
Errors · 401
StatusWhen
401Missing, expired or invalid credentials
POST /v1/account/api-keys/{key_id}/rotate #

Rotate atomically

rotateKey captured live

Request

curl -X POST https://api.ollacore.com/v1/account/api-keys/key-id-main/rotate \
  -H "Authorization: Bearer as_…" \
  -H "Content-Type: application/json" \
  -d '{}'
{}
ParameterTypeDescription
key_id path required string The key's public id (ak_live_… or ak_test_…), as returned when it was created or listed.
X-Request-Id header string Your own id for this request. It is returned in the response's X-Request-Id header and attached to every log line kept for the request, so quote it when you contact support. Use printable ASCII. Without it, the server assigns a UUID.

Response · 200

{
  "api_key": "ak_live_EXAMPLE.NOT_A_REAL_KEY",
  "key_id": "ak_live_616b8de93a24dfbf2c5839186fd5b29a"
}
Response fields (2)
FieldTypeDescription
key_id string The replacement key's id. The old key is revoked in the same step.
api_key string The replacement key, ak_<env>_<id>.<secret>. Shown once; store it now.
Errors · 401 · 404
StatusWhen
401Missing, expired or invalid credentials
404not an owned, live key
DELETE /v1/account/api-keys/{key_id} #

Revoke

deleteKey captured live

Request

curl -X DELETE https://api.ollacore.com/v1/account/api-keys/ak_live_e8177c7859fe3139043b58fff01924bd \
  -H "Authorization: Bearer as_…"
ParameterTypeDescription
key_id path required string The key's public id (ak_live_… or ak_test_…).
X-Request-Id header string Your own id for this request. It is returned in the response's X-Request-Id header and attached to every log line kept for the request, so quote it when you contact support. Use printable ASCII. Without it, the server assigns a UUID.

Response · 200

{
  "revoked": true
}
Response fields (1)
FieldTypeDescription
revoked boolean True once the key no longer works.
Errors · 401 · 404
StatusWhen
401Missing, expired or invalid credentials
404not an owned, live key

Directory apps #

POST /v1/account/directory-apps #

Provision an app (webhook or SMS provider)

createDirectoryApp captured live

Request

curl -X POST https://api.ollacore.com/v1/account/directory-apps \
  -H "Authorization: Bearer as_…" \
  -H "Content-Type: application/json" \
  -d '{"delivery_webhook_url":"https://hooks.example.com/hook"}'
{
  "delivery_webhook_url": "https://hooks.example.com/hook"
}
ParameterTypeDescription
X-Request-Id header string Your own id for this request. It is returned in the response's X-Request-Id header and attached to every log line kept for the request, so quote it when you contact support. Use printable ASCII. Without it, the server assigns a UUID.

Request fields

FieldTypeDescription
delivery_webhook_url string (uri) Webhook mode: where we POST each OTP, signed, for you to deliver. Must be a public https:// URL: one whose address is private, loopback or link-local is refused with 400 here, and every delivery checks again. A name that doesn't resolve yet is accepted now and refused at delivery if it still doesn't. Set this or provider, not both.
provider object Provider mode: your own SMS vendor account, which we call to send the OTP. Set this or delivery_webhook_url, not both. Credentials cannot be updated later; rotate by creating a new app.
provider.kind required if its parent is sent one of: twilio, plivo, msg91 Which SMS vendor. config holds that vendor's credentials and is validated for it now.
provider.config required if its parent is sent object Vendor-specific credentials; validated for kind at creation.

Response · 200

{
  "app_id": "da_03270a6c821fcca6c63a2049d93b62fe",
  "delivery_mode": "webhook",
  "delivery_secret": "dsec_EXAMPLE_NOT_A_REAL_SECRET",
  "delivery_webhook_url": "https://hooks.example.com/hook"
}
Response fields (4)
FieldTypeDescription
app_id string The app's public id. Safe to ship in your mobile build; the directory endpoints take it to find your tenant.
delivery_mode one of: webhook, provider How OTPs reach users: webhook or provider.
delivery_secret string, nullable HMAC secret, shown once (webhook mode only)
delivery_webhook_url string, nullable The delivery webhook, in webhook mode; null in provider mode.
Errors · 400 · 401
StatusWhen
400Invalid request: both or neither of delivery_webhook_url and provider; a provider configuration of the wrong shape; or a delivery_webhook_url that is not https:// or whose address is not public (private, loopback, link-local or otherwise reserved). A name that does not resolve yet is accepted.
401Missing, expired or invalid credentials
GET /v1/account/directory-apps #

List apps and which push transports are configured

listDirectoryApps captured live

Request

curl -X GET https://api.ollacore.com/v1/account/directory-apps \
  -H "Authorization: Bearer as_…"
ParameterTypeDescription
X-Request-Id header string Your own id for this request. It is returned in the response's X-Request-Id header and attached to every log line kept for the request, so quote it when you contact support. Use printable ASCII. Without it, the server assigns a UUID.

Response · 200

{
  "directory_apps": [
    {
      "app_id": "da_03270a6c821fcca6c63a2049d93b62fe",
      "created_at": "2026-01-15T09:30:01Z",
      "delivery_mode": "webhook",
      "delivery_webhook_url": "https://hooks.example.com/hook",
      "push_apns": false,
      "push_fcm": false
    }
  ]
}
Response fields (1)
FieldTypeDescription
directory_apps array of object The account's directory apps. Secrets are never returned.
Errors · 401
StatusWhen
401Missing, expired or invalid credentials
DELETE /v1/account/directory-apps/{app_id} #

Delete an app

deleteDirectoryApp captured live

Request

curl -X DELETE https://api.ollacore.com/v1/account/directory-apps/da_03270a6c821fcca6c63a2049d93b62fe \
  -H "Authorization: Bearer as_…"
ParameterTypeDescription
app_id path required string The directory app's public id.
X-Request-Id header string Your own id for this request. It is returned in the response's X-Request-Id header and attached to every log line kept for the request, so quote it when you contact support. Use printable ASCII. Without it, the server assigns a UUID.

Response · 200

{
  "deleted": true
}
Response fields (1)
FieldTypeDescription
deleted boolean True once the app is gone. Its users and data stay in the tenant.
Errors · 401 · 404
StatusWhen
401Missing, expired or invalid credentials
404not an owned app
PUT /v1/account/directory-apps/{app_id}/push #

Set FCM/APNs credentials (write-only)

setPush captured live placeholder credentials

Request

curl -X PUT https://api.ollacore.com/v1/account/directory-apps/da_03270a6c821fcca6c63a2049d93b62fe/push \
  -H "Authorization: Bearer as_…" \
  -H "Content-Type: application/json" \
  -d '{"fcm":{"service_account":{"project_id":"my-firebase-project","client_email":"[email protected]","private_key":"-----BEGIN PRIVATE KEY-----\n<redacted>\n-----END PRIVATE KEY-----"}},"apns":{"p8":"-----BEGIN PRIVATE KEY-----\n<redacted>\n-----END PRIVATE KEY-----","key_id":"ABC123DEFG","team_id":"TEAM123456","topic":"com.example.chat","env":"production"}}'
{
  "fcm": {
    "service_account": {
      "project_id": "my-firebase-project",
      "client_email": "[email protected]",
      "private_key": "-----BEGIN PRIVATE KEY-----\n<redacted>\n-----END PRIVATE KEY-----"
    }
  },
  "apns": {
    "p8": "-----BEGIN PRIVATE KEY-----\n<redacted>\n-----END PRIVATE KEY-----",
    "key_id": "ABC123DEFG",
    "team_id": "TEAM123456",
    "topic": "com.example.chat",
    "env": "production"
  }
}
ParameterTypeDescription
app_id path required string The directory app's public id.
X-Request-Id header string Your own id for this request. It is returned in the response's X-Request-Id header and attached to every log line kept for the request, so quote it when you contact support. Use printable ASCII. Without it, the server assigns a UUID.

Request fields

FieldTypeDescription
fcm object, nullable FCM credentials: service_account is the Google service-account JSON. Omit or null to clear FCM, because this call replaces both sides.
fcm.service_account required if its parent is sent object Google service-account JSON (project_id, client_email, private_key, ...)
apns object, nullable APNs credentials. Omit or null to clear APNs, because this call replaces both sides.
apns.p8 required if its parent is sent string The contents of the APNs .p8 key file (PEM).
apns.key_id required if its parent is sent string The APNs key's 10-character id.
apns.team_id required if its parent is sent string Your Apple developer team id.
apns.topic required if its parent is sent string The app's bundle id.
apns.env one of: sandbox, production default "production" production (TestFlight and App Store) or sandbox (debug builds). Defaults to production. The wrong one fails silently.

Response · 200

{
  "push_apns": true,
  "push_fcm": true
}
Response fields (2)
FieldTypeDescription
push_fcm boolean Whether FCM credentials are now stored.
push_apns boolean Whether APNs credentials are now stored.
Errors · 400 · 401 · 404
StatusWhen
400Invalid push config
401Missing, expired or invalid credentials
404No such room, message, member or attachment

Errors on this plane #

Every failure uses the same body — code and message. These were triggered deliberately against the live API.

401 · no Authorization header

{
  "code": "unauthorized",
  "message": "unauthorized: missing Authorization header"
}

401 · an as_ account session on the server plane

{
  "code": "unauthorized",
  "message": "unauthorized: malformed API key"
}

The full code list and retry guidance is on Errors & rate limits.