Directory (end-user) API
The turnkey identity plane. Your client calls these directly.
Credential: du_ directory session — or none for OTP · scheme du_ directory session
35 operations · 35 captured against the live API.
Sign-in & profile #
Request a one-time code (unauthenticated)
Request
curl -X POST https://api.ollacore.com/v1/directory/otp/request \
-H "Content-Type: application/json" \
-d '{"app_id":"da_3a0a2cfaabd34b7dbfb4ecd5033b0c5f","phone":"+15550001111"}' {
"app_id": "da_3a0a2cfaabd34b7dbfb4ecd5033b0c5f",
"phone": "+15550001111"
} | Parameter | Type | Description |
|---|---|---|
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
| Field | Type | Description |
|---|---|---|
app_id required | string | Your directory app's public id. |
phone required | string | E.164 |
Response · 200
{
"dispatched": true,
"expires_at": "2026-01-15T09:35:42Z"
} Response fields (2)
| Field | Type | Description |
|---|---|---|
dispatched | boolean | True when a code was handed to your webhook or SMS vendor. The answer is the same whether or not the number is registered. |
expires_at | string (date-time) | When the code stops working: 5 minutes after it was issued. |
Errors · 404 · 429
| Status | When |
|---|---|
404 | unknown app |
429 | rate limited |
Verify and receive a du_ session
Request
curl -X POST https://api.ollacore.com/v1/directory/otp/verify \
-H "Content-Type: application/json" \
-d '{"app_id":"da_3a0a2cfaabd34b7dbfb4ecd5033b0c5f","phone":"+15550001111","code":"481920"}' {
"app_id": "da_3a0a2cfaabd34b7dbfb4ecd5033b0c5f",
"phone": "+15550001111",
"code": "481920"
} | Parameter | Type | Description |
|---|---|---|
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
| Field | Type | Description |
|---|---|---|
app_id required | string | Your directory app's public id. |
phone required | string | The same E.164 number the code was sent to. |
code required | string | The 6-digit code. At most 5 attempts per code; each code works once. |
Response · 200
{
"session_token": "as_EXAMPLE_SESSION",
"user_id": "4a98e767-a426-47e9-89a0-c499b54d2904",
"display_name": "Alice Nakamura"
} Response fields (3)
| Field | Type | Description |
|---|---|---|
session_token | string | The du_… directory session for this user, valid 30 days. Store it securely on the device. |
user_id | string (uuid) | The directory user's id. It is also their chat principal_id. |
display_name | string, nullable | The user's display name, or null if not set yet. |
Errors · 401
| Status | When |
|---|---|
401 | Missing, expired or invalid credentials |
Revoke this session (or every device)
Request
curl -X POST https://api.ollacore.com/v1/directory/logout \
-H "Authorization: Bearer du_…" \
-H "Content-Type: application/json" \
-d '{"all_devices":false}' {
"all_devices": false
} | Parameter | Type | Description |
|---|---|---|
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
| Field | Type | Description |
|---|---|---|
all_devices | boolean default false | Revoke every session for this user, not just the one presented. |
Response · 200
{
"logged_out": true,
"sessions_revoked": 1
} Response fields (2)
| Field | Type | Description |
|---|---|---|
logged_out | boolean | Always true: the session (or every session, with all_devices) no longer works. |
sessions_revoked | integer | How many sessions were revoked. |
Errors · 401
| Status | When |
|---|---|
401 | Missing, expired or invalid credentials |
Current user: id, phone, display_name, about, avatar_version
Request
curl -X GET https://api.ollacore.com/v1/directory/me \
-H "Authorization: Bearer du_…" | Parameter | Type | Description |
|---|---|---|
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
{
"id": "4a98e767-a426-47e9-89a0-c499b54d2904",
"phone": "+15550001111",
"display_name": "Alice Nakamura",
"about": "Ships things. Slow to reply at weekends.",
"avatar_version": null
} Response fields (5)
| Field | Type | Description |
|---|---|---|
id required | string (uuid) | The user's id, which is also their chat principal_id. |
phone required | string | The user's verified phone number, E.164. |
display_name required | string, nullable | The user's display name, or null if not set. |
about required | string, nullable max length 256 | The profile line, up to 256 characters; null when not set. |
avatar_version required | string (date-time), nullable | When the current profile photo was set; null when there is none. The value to cache the picture by: fetch GET /v1/directory/users/{user_id}/avatar once per version (its ETag is this value). |
Errors · 401
| Status | When |
|---|---|
401 | Missing, expired or invalid credentials |
Update display name and/or about line
Request
curl -X PATCH https://api.ollacore.com/v1/directory/me \
-H "Authorization: Bearer du_…" \
-H "Content-Type: application/json" \
-d '{"display_name":"Alice Nakamura","about":"Ships things. Slow to reply at weekends."}' {
"display_name": "Alice Nakamura",
"about": "Ships things. Slow to reply at weekends."
} | Parameter | Type | Description |
|---|---|---|
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
| Field | Type | Description |
|---|---|---|
display_name | string max length 128 | New display name, 1–128 characters after trimming. |
about | string max length 256 | New profile line, up to 256 characters after trimming; an empty string clears it. |
Response · 200
{
"id": "4a98e767-a426-47e9-89a0-c499b54d2904",
"phone": "+15550001111",
"display_name": "Alice Nakamura",
"about": "Ships things. Slow to reply at weekends.",
"avatar_version": null
} Response fields (5)
| Field | Type | Description |
|---|---|---|
id required | string (uuid) | The user's id, which is also their chat principal_id. |
phone required | string | The user's verified phone number, E.164. |
display_name required | string, nullable | The user's display name, or null if not set. |
about required | string, nullable max length 256 | The profile line, up to 256 characters; null when not set. |
avatar_version required | string (date-time), nullable | When the current profile photo was set; null when there is none. The value to cache the picture by: fetch GET /v1/directory/users/{user_id}/avatar once per version (its ETag is this value). |
Errors · 400 · 401
| Status | When |
|---|---|
400 | Nothing to update, a display name outside 1–128 characters, or an about line over 256. |
401 | Missing, expired or invalid credentials |
Start a profile-photo upload (JPEG/PNG/WebP/GIF, ≤ 2 MiB)
Request
curl -X POST https://api.ollacore.com/v1/directory/me/avatar/init \
-H "Authorization: Bearer du_…" \
-H "Content-Type: application/json" \
-d '{"declared_mime":"image/jpeg","byte_size":160}' {
"declared_mime": "image/jpeg",
"byte_size": 160
} | Parameter | Type | Description |
|---|---|---|
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
| Field | Type | Description |
|---|---|---|
declared_mime required | one of: image/jpeg, image/png, image/webp, image/gif | The image type you will PUT. |
byte_size required | integer (int64) min 1 · max 2097152 | Exact size of the bytes, at most 2 MiB. |
Response · 200
{
"expires_at": "2026-01-15T09:35:43Z",
"max_bytes": 2097152,
"upload_id": "3a7d0ead-8ffa-4194-b38e-2e5c0ce04738",
"upload_url": "https://files.example.com/objects/…?X-Amz-Signature=…"
} Response fields (4)
| Field | Type | Description |
|---|---|---|
upload_id required | string (uuid) | Hand this to complete after the PUT. |
upload_url required | string (uri) | Presigned PUT for the photo bytes. Send the raw bytes with the declared Content-Type. |
expires_at required | string (date-time) | When the upload URL stops working. |
max_bytes required | integer (int64) | The size cap, 2 MiB. Downscale on the device first. |
Errors · 400 · 401 · 415 · 429
| Status | When |
|---|---|
400 | byte_size outside 1..=2 MiB. |
401 | Missing, expired or invalid credentials |
415 | declared_mime is not an image type a profile photo may be. |
429 | Rate limit exceeded |
Make the uploaded bytes your photo — verified before it answers
Request
curl -X POST https://api.ollacore.com/v1/directory/me/avatar/complete \
-H "Authorization: Bearer du_…" \
-H "Content-Type: application/json" \
-d '{"upload_id":"3a7d0ead-8ffa-4194-b38e-2e5c0ce04738"}' {
"upload_id": "3a7d0ead-8ffa-4194-b38e-2e5c0ce04738"
} | Parameter | Type | Description |
|---|---|---|
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
| Field | Type | Description |
|---|---|---|
upload_id required | string (uuid) | From init. |
Response · 200
{
"id": "4a98e767-a426-47e9-89a0-c499b54d2904",
"phone": "+15550001111",
"display_name": "Alice Nakamura",
"about": "Ships things. Slow to reply at weekends.",
"avatar_version": "2026-01-15T09:30:44Z"
} Response fields (5)
| Field | Type | Description |
|---|---|---|
id required | string (uuid) | The user's id, which is also their chat principal_id. |
phone required | string | The user's verified phone number, E.164. |
display_name required | string, nullable | The user's display name, or null if not set. |
about required | string, nullable max length 256 | The profile line, up to 256 characters; null when not set. |
avatar_version required | string (date-time), nullable | When the current profile photo was set; null when there is none. The value to cache the picture by: fetch GET /v1/directory/users/{user_id}/avatar once per version (its ETag is this value). |
Errors · 400 · 401 · 409 · 415
| Status | When |
|---|---|
400 | The uploaded object is larger than 2 MiB (it is removed). |
401 | Missing, expired or invalid credentials |
409 | Nothing has been uploaded for this upload_id yet. |
415 | The bytes are not an image, or could not be decoded (the object is removed). |
Remove your profile photo
Request
curl -X DELETE https://api.ollacore.com/v1/directory/me/avatar \
-H "Authorization: Bearer du_…" | Parameter | Type | Description |
|---|---|---|
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
{
"id": "4a98e767-a426-47e9-89a0-c499b54d2904",
"phone": "+15550001111",
"display_name": "Alice Nakamura",
"about": "Ships things. Slow to reply at weekends.",
"avatar_version": null
} Response fields (5)
| Field | Type | Description |
|---|---|---|
id required | string (uuid) | The user's id, which is also their chat principal_id. |
phone required | string | The user's verified phone number, E.164. |
display_name required | string, nullable | The user's display name, or null if not set. |
about required | string, nullable max length 256 | The profile line, up to 256 characters; null when not set. |
avatar_version required | string (date-time), nullable | When the current profile photo was set; null when there is none. The value to cache the picture by: fetch GET /v1/directory/users/{user_id}/avatar once per version (its ETag is this value). |
Errors · 401
| Status | When |
|---|---|
401 | Missing, expired or invalid credentials |
A user's photo: 302 to the bytes, ETag = avatar_version
Request
curl -X GET https://api.ollacore.com/v1/directory/users/4a98e767-a426-47e9-89a0-c499b54d2904/avatar?size=thumb \
-H "Authorization: Bearer du_…" | Parameter | Type | Description |
|---|---|---|
user_id path required | string (uuid) | A user of your tenant (yourself included). |
size query | one of: thumb, full default "thumb" | thumb: a JPEG no larger than 256 px on its longest side. full: the bytes as uploaded. |
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 · 302
Empty body.
Errors · 400 · 401 · 404
| Status | When |
|---|---|
400 | size is neither thumb nor full. |
401 | Missing, expired or invalid credentials |
404 | No such room, message, member or attachment |
Contacts & conversations #
Which phone numbers are registered (≤500)
Request
curl -X POST https://api.ollacore.com/v1/directory/contacts/lookup \
-H "Authorization: Bearer du_…" \
-H "Content-Type: application/json" \
-d '{"phones":["+15550002222","+15550009999"]}' {
"phones": [
"+15550002222",
"+15550009999"
]
} | Parameter | Type | Description |
|---|---|---|
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
| Field | Type | Description |
|---|---|---|
phones required | array of string max 500 items | Up to 500 phone numbers, E.164. Invalid numbers are dropped rather than failing the batch. |
Response · 200
{
"contacts": [
{
"about": null,
"avatar_version": null,
"display_name": "malavika rajesh",
"phone": "+15550002222",
"user_id": "0b925a2d-944a-4f1d-a761-56d24db90341"
}
]
} Response fields (6)
| Field | Type | Description |
|---|---|---|
contacts | array of object | The numbers that belong to registered users in your tenant. Other tenants' users are never disclosed. |
contacts[]. | string (uuid) | The user's id, which is also their chat principal_id. |
contacts[]. | string | The matched number, E.164. |
contacts[]. | string, nullable | The user's display name, or null if not set. |
contacts[]. | string, nullable max length 256 | The profile line, up to 256 characters; null when not set. |
contacts[]. | string (date-time), nullable | When their current profile photo was set; null when there is none. The value to cache the picture by: fetch GET /v1/directory/users/{user_id}/avatar once per version (its ETag is this value). |
Errors · 401
| Status | When |
|---|---|
401 | Missing, expired or invalid credentials |
Open a 1:1 (idempotent; blocked across a block)
Request
curl -X POST https://api.ollacore.com/v1/directory/conversations/direct \
-H "Authorization: Bearer du_…" \
-H "Content-Type: application/json" \
-d '{"peer_user_id":"0b925a2d-944a-4f1d-a761-56d24db90341"}' {
"peer_user_id": "0b925a2d-944a-4f1d-a761-56d24db90341"
} | Parameter | Type | Description |
|---|---|---|
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
| Field | Type | Description |
|---|---|---|
peer_user_id required | string (uuid) | The other person's directory user id, in your tenant. |
Response · 200
{
"room_id": "eb0a0da1-5344-483f-8b18-b95bfc4d1e36",
"kind": "direct"
} Response fields (2)
| Field | Type | Description |
|---|---|---|
room_id | string (uuid) | The 1:1 room. The same pair always gets the same room. |
kind | string | Always direct. |
Errors · 400 · 401 · 403 · 404
| Status | When |
|---|---|
400 | Invalid (e.g. self) |
401 | Missing, expired or invalid credentials |
403 | The direct conversation is frozen by a block (code blocked): one of the two people has blocked the other. Neither can send, react, type or start a call in it, and neither can open a new direct conversation with the other, until the block is lifted. History stays readable. Both sides get this answer; it does not say who blocked whom. |
404 | No such room, message, member or attachment |
Create a group
Request
curl -X POST https://api.ollacore.com/v1/directory/conversations/group \
-H "Authorization: Bearer du_…" \
-H "Content-Type: application/json" \
-d '{"member_user_ids":["0b925a2d-944a-4f1d-a761-56d24db90341"],"name":"Weekend plans"}' {
"member_user_ids": [
"0b925a2d-944a-4f1d-a761-56d24db90341"
],
"name": "Weekend plans"
} | Parameter | Type | Description |
|---|---|---|
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
| Field | Type | Description |
|---|---|---|
member_user_ids required | array of string (uuid) max 4999 items | The other members' directory user ids, all in your tenant. You are added as owner. A group holds at most 5,000 members including you; anything larger is 400 before any lookup. |
name | string, nullable max length 128 | Optional group name, up to 128 characters. |
Response · 200
{
"room_id": "60f99e3b-2084-4bb5-9adb-527ee9907673",
"kind": "group",
"name": "Weekend plans"
} Response fields (6)
| Field | Type | Description |
|---|---|---|
room_id | string (uuid) | The new group's room. Each call creates a new group. |
kind | string | Always group. |
name | string, nullable | The group's name, or null. |
not_added | array of NotAdded | People you named who were not added, with the reason — only blocked today: they have blocked you. Absent or empty when everyone was added. |
not_added[]. required if its parent is sent | string (uuid) | Someone you named who was not added. |
not_added[]. required if its parent is sent | one of: blocked | blocked: they have blocked you. |
Errors · 401 · 403 · 404
| Status | When |
|---|---|
401 | Missing, expired or invalid credentials |
403 | The direct conversation is frozen by a block (code blocked): one of the two people has blocked the other. Neither can send, react, type or start a call in it, and neither can open a new direct conversation with the other, until the block is lifted. History stays readable. Both sides get this answer; it does not say who blocked whom. |
404 | No such room, message, member or attachment |
List conversations
Request
curl -X GET https://api.ollacore.com/v1/directory/conversations \
-H "Authorization: Bearer du_…" | Parameter | Type | Description |
|---|---|---|
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
{
"conversations": [
{
"created_at": "2026-01-15T09:30:44Z",
"description": null,
"icon_attachment_id": null,
"kind": "group",
"name": "Weekend plans",
"room_id": "60f99e3b-2084-4bb5-9adb-527ee9907673"
},
{
"created_at": "2026-01-15T08:20:10Z",
"description": "Saturday hike, then dinner at eight.",
"icon_attachment_id": null,
"kind": "group",
"name": "Weekend plans",
"room_id": "1cac5f45-0101-442b-a6cf-bdc9136a4c55"
},
{
"created_at": "2026-01-15T05:11:50Z",
"description": "Saturday hike, then dinner at eight.",
"icon_attachment_id": null,
"kind": "group",
"name": "Weekend plans",
"room_id": "8ef5c24c-eca5-4c18-b1c3-bb4e86b24632"
},
{
"created_at": "2026-01-14T05:48:54Z",
"description": "Saturday hike, then dinner at eight.",
"icon_attachment_id": null,
"kind": "group",
"name": "Weekend plans",
"room_id": "94a7993d-f741-47dc-b524-dc63a8986899"
},
{
"created_at": "2026-01-14T05:44:03Z",
"description": "Saturday hike, then dinner at eight.",
"icon_attachment_id": null,
"kind": "group",
"name": "Weekend plans",
"room_id": "b7740fb5-02e4-4095-980c-abd1f098ae37"
},
{
"created_at": "2026-01-07T02:12:15Z",
"description": "Saturday hike, then dinner at eight.",
"icon_attachment_id": null,
"kind": "group",
"name": "Weekend plans",
"room_id": "aca2ceb1-e310-4e14-8882-d8e966b7d712"
},
{
"created_at": "2026-01-07T02:10:38Z",
"description": "Saturday hike, then dinner at eight.",
"icon_attachment_id": null,
"kind": "group",
"name": "Weekend plans",
"room_id": "b5e03d35-ea1d-403e-9a87-02e614aee58a"
},
{
"created_at": "2026-01-04T06:25:11Z",
"description": null,
"icon_attachment_id": null,
"kind": "group",
"name": "testing me",
"room_id": "61f13be9-cf5b-4e1c-9d33-e39872d872c7"
},
{
"created_at": "2026-01-02T08:34:58Z",
"description": null,
"icon_attachment_id": null,
"kind": "group",
"name": "test group",
"room_id": "6eb71e13-fe76-4e5a-a9c2-6c197c5f1400"
},
{
"created_at": "2026-01-02T06:08:08Z",
"description": null,
"icon_attachment_id": null,
"kind": "group",
"name": "Live Verify Group 1791189343212",
"room_id": "9e052209-79c3-487b-9a5a-ad43bbceb481"
},
{
"created_at": "2025-12-26T17:24:52Z",
"description": null,
"icon_attachment_id": null,
"kind": "direct",
"name": null,
"room_id": "c8366e3b-a43d-4e20-91ef-567e1287e110"
},
{
"created_at": "2025-12-26T06:22:28Z",
"description": null,
"icon_attachment_id": null,
"kind": "group",
"name": "Backend Test Grp",
"room_id": "36bf8624-46f1-40a0-9ead-1b6ad5a1163f"
},
{
"created_at": "2025-12-26T05:45:00Z",
"description": null,
"icon_attachment_id": null,
"kind": "group",
"name": "sdfghjklllkjhgfdcvbhjklkmnbv",
"room_id": "d4ac2357-7773-4840-b9ac-f4ebc7978267"
},
{
"created_at": "2025-12-23T08:09:04Z",
"description": null,
"icon_attachment_id": null,
"kind": "group",
"name": "Self Media Group",
"room_id": "fadcd831-d379-493d-be50-222ecbf697e9"
},
{
"created_at": "2025-12-21T08:10:13Z",
"description": null,
"icon_attachment_id": null,
"kind": "group",
"name": "Group call",
"room_id": "e23fb102-5878-4b14-a637-a6878a202935"
},
{
"created_at": "2025-12-21T08:02:17Z",
"description": null,
"icon_attachment_id": null,
"kind": "group",
"name": "TestGroup-1790159400517",
"room_id": "4d55f4fa-516c-4ddc-8e08-18719784882d"
},
{
"created_at": "2025-12-09T06:34:28Z",
"description": null,
"icon_attachment_id": null,
"kind": "group",
"name": "Weekend plans",
"room_id": "dc18e5c2-e264-4ead-be79-1f78faf15a54"
},
{
"created_at": "2025-12-09T04:29:48Z",
"description": null,
"icon_attachment_id": null,
"kind": "group",
"name": "QA Test Group",
"room_id": "5e38f7cd-e6f7-428e-b3ec-1d57d6fc4025"
},
{
"created_at": "2025-12-09T04:28:31Z",
"description": null,
"icon_attachment_id": null,
"kind": "group",
"name": "QA Test Group",
"room_id": "d7f66e06-79d0-4cd8-9f13-6795b4ac692f"
},
{
"created_at": "2025-12-08T15:56:18Z",
"description": null,
"icon_attachment_id": null,
"kind": "group",
"name": "Weekend plans",
"room_id": "6c0db0aa-7c88-410c-bcf1-e0f17cbe0cdf"
},
{
"created_at": "2025-12-08T15:53:16Z",
"description": null,
"icon_attachment_id": null,
"kind": "group",
"name": "Weekend plans",
"room_id": "ee286c5c-7607-453f-8165-8a40f3e19214"
},
{
"created_at": "2025-12-08T15:43:20Z",
"description": null,
"icon_attachment_id": null,
"kind": "group",
"name": "Weekend plans",
"room_id": "a970b461-8d3c-4c2e-88c2-77beee06a75f"
},
{
"created_at": "2025-12-08T15:40:48Z",
"description": null,
"icon_attachment_id": null,
"kind": "group",
"name": "Weekend plans",
"room_id": "07191895-7185-4474-b1fd-e804fc432f1a"
},
{
"created_at": "2025-12-08T15:38:48Z",
"description": null,
"icon_attachment_id": null,
"kind": "group",
"name": "Weekend plans",
"room_id": "f9f4c84c-1028-46de-905b-214423a81304"
},
{
"created_at": "2025-12-08T15:38:48Z",
"description": null,
"icon_attachment_id": null,
"kind": "direct",
"name": null,
"room_id": "eb0a0da1-5344-483f-8b18-b95bfc4d1e36"
}
]
} Response fields (7)
| Field | Type | Description |
|---|---|---|
conversations | array of object | The caller's directory conversations. |
conversations[]. | string (uuid) | The conversation's room. Mint a token for it to chat or call. |
conversations[]. | one of: direct, group | direct (two people) or group. |
conversations[]. | string, nullable | The group's name; null for a direct conversation. |
conversations[]. | string, nullable max length 1024 | The group's description, up to 1024 characters; null when there is none. |
conversations[]. | string (uuid), nullable | The group's icon: an image attachment of the group's own room, or null. Fetch it like any picture posted there — GET /v1/rooms/{room_id}/attachments/{attachment_id}/download with a room token — and cache it by id; a changed icon is a new id. |
conversations[]. | string (date-time) | When the conversation was created. |
Errors · 401
| Status | When |
|---|---|
401 | Missing, expired or invalid credentials |
Mint a room token
Request
curl -X GET https://api.ollacore.com/v1/directory/conversations/eb0a0da1-5344-483f-8b18-b95bfc4d1e36/token?device_id=dev-alice-phone \
-H "Authorization: Bearer du_…" | Parameter | Type | Description |
|---|---|---|
room_id path required | string (uuid) | The conversation's room. The caller must be a member (403 otherwise); a room in another tenant is 404. |
device_id query | string | Identifies this device. Needed for the E2EE endpoints, and to join a call from two devices at once. |
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
{
"access_token": "eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCIsImtpZCI6ImEwM2I1NjQ4MjM3YjlmZWIifQ.eyJpc3MiOiJjaGF0Ym94LWJhY2tlbmQiLCJhdWQiOiJjaGF0Ym94LXJlYWx0aW1lIiwic3ViIjoiNGE5OGU3NjctYTQyNi00N2U5LTg5YTAtYzQ5OWI1NGQyOTA0IiwidGlkIjoiYWNjdF9lZmFmN2YwMWEzNzM0NTNiYjEwMDQ2YzcyYzNiYjdiYiIsInJpZCI6ImViMGEwZGExLTUzNDQtNDgzZi04YjE4LWI5NWJmYzRkMWUzNiIsInJvbGUiOiJtZW1iZXIiLCJwZXJtaXNzaW9ucyI6WyJjaGF0OnNlbmQiLCJjaGF0Omhpc3RvcnkiLCJhdHRhY2htZW50OnVwbG9hZCIsImF0dGFjaG1lbnQ6ZG93bmxvYWQiLCJydGM6cHVibGlzaCIsInJ0YzpzdWJzY3JpYmUiXSwiZGlkIjoiZGV2LWFsaWNlLXBob25lIiwianRpIjoiY2MxYjhmMDEtNmVkMS00OWZmLWIyNGItZjFkMzA3NjAyYzc1IiwiaWF0IjoxNzkyMzI0NzA4LCJuYmYiOjE3OTIzMjQ3MDgsImV4cCI6MTc5MjMyNTMwOH0.SIGNATURE_REMOVED",
"expires_at": "2026-01-15T09:40:45Z",
"rtc_websocket_url": "wss://api.ollacore.com/v1/rtc/ws",
"chat_websocket_url": "wss://api.ollacore.com/v1/chat/ws",
"ice_servers": [
{
"urls": [
"stun:api.ollacore.com:3478"
]
},
{
"urls": [
"turn:api.ollacore.com:3478",
"turns:api.ollacore.com:5349"
],
"username": "1789064267:alice",
"credential": "EXAMPLE_TURN_CREDENTIAL="
}
]
} Response fields (8)
| Field | Type | Description |
|---|---|---|
access_token required | string | The room-scoped session token (an Ed25519-signed JWT). Present it as Authorization: Bearer … over HTTP and as the WebSocket subprotocol bearer.<token>, never in a URL. |
expires_at required | string (date-time) | When the token expires. Mint a new one before then; a socket closes with 4401 at expiry. |
rtc_websocket_url required | string (uri) | The call-signalling WebSocket URL. |
chat_websocket_url required | string (uri) | The chat WebSocket URL. |
ice_servers required | array of object | STUN and TURN servers for WebRTC, with short-lived TURN credentials. Pass them to RTCPeerConnection unchanged. |
ice_servers[]. required | array of string | The server URLs. They never carry a ?transport= query, which Safari refuses. |
ice_servers[]. | string | expiry_unix:principal — ephemeral, 600 s |
ice_servers[]. | string | base64(HMAC-SHA1(turn_secret, username)) |
Errors · 401 · 403 · 404
| Status | When |
|---|---|
401 | Missing, expired or invalid credentials |
403 | Authenticated, but the token is not scoped to this room or principal |
404 | No such room, message, member or attachment |
Chat list: peer, last message, unread, muted_until
Request
curl -X GET https://api.ollacore.com/v1/directory/inbox?limit=30 \
-H "Authorization: Bearer du_…" | Parameter | Type | Description |
|---|---|---|
limit query | integer default 50 · min 1 · max 200 | Maximum conversations, 1–200. Defaults to 50. |
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
{
"conversations": [
{
"description": "Saturday hike, then dinner at eight.",
"icon_attachment_id": null,
"kind": "group",
"last_message": {
"created_at": "2026-01-15T09:30:45Z",
"event_seq": 5208,
"kind": "system",
"preview": "system",
"sender_id": "4a98e767-a426-47e9-89a0-c499b54d2904"
},
"muted_until": null,
"name": "Weekend plans",
"peer": null,
"room_id": "60f99e3b-2084-4bb5-9adb-527ee9907673",
"unread_count": 0
},
{
"description": "Saturday hike, then dinner at eight.",
"icon_attachment_id": null,
"kind": "group",
"last_message": {
"created_at": "2026-01-15T08:20:11Z",
"event_seq": 5196,
"kind": "system",
"preview": "system",
"sender_id": "4a98e767-a426-47e9-89a0-c499b54d2904"
},
"muted_until": null,
"name": "Weekend plans",
"peer": null,
"room_id": "1cac5f45-0101-442b-a6cf-bdc9136a4c55",
"unread_count": 0
},
{
"description": "Saturday hike, then dinner at eight.",
"icon_attachment_id": null,
"kind": "group",
"last_message": {
"created_at": "2026-01-15T05:11:51Z",
"event_seq": 5184,
"kind": "system",
"preview": "system",
"sender_id": "4a98e767-a426-47e9-89a0-c499b54d2904"
},
"muted_until": null,
"name": "Weekend plans",
"peer": null,
"room_id": "8ef5c24c-eca5-4c18-b1c3-bb4e86b24632",
"unread_count": 0
},
{
"description": "Saturday hike, then dinner at eight.",
"icon_attachment_id": null,
"kind": "group",
"last_message": {
"created_at": "2026-01-14T05:48:55Z",
"event_seq": 5131,
"kind": "system",
"preview": "system",
"sender_id": "4a98e767-a426-47e9-89a0-c499b54d2904"
},
"muted_until": null,
"name": "Weekend plans",
"peer": null,
"room_id": "94a7993d-f741-47dc-b524-dc63a8986899",
"unread_count": 0
},
{
"description": "Saturday hike, then dinner at eight.",
"icon_attachment_id": null,
"kind": "group",
"last_message": {
"created_at": "2026-01-14T05:44:04Z",
"event_seq": 5122,
"kind": "system",
"preview": "system",
"sender_id": "4a98e767-a426-47e9-89a0-c499b54d2904"
},
"muted_until": null,
"name": "Weekend plans",
"peer": null,
"room_id": "b7740fb5-02e4-4095-980c-abd1f098ae37",
"unread_count": 0
},
{
"description": null,
"icon_attachment_id": null,
"kind": "direct",
"last_message": {
"created_at": "2026-01-09T06:55:18Z",
"event_seq": 4842,
"kind": "text",
"preview": "",
"sender_id": "4a98e767-a426-47e9-89a0-c499b54d2904"
},
"muted_until": "2026-01-22T09:30:47Z",
"name": null,
"peer": {
"avatar_version": null,
"display_name": "malavika rajesh",
"phone": "+15550002222",
"user_id": "0b925a2d-944a-4f1d-a761-56d24db90341"
},
"room_id": "eb0a0da1-5344-483f-8b18-b95bfc4d1e36",
"unread_count": 5
},
{
"description": null,
"icon_attachment_id": null,
"kind": "group",
"last_message": {
"created_at": "2026-01-08T11:56:21Z",
"event_seq": 4733,
"kind": "text",
"preview": "cna you see this",
"sender_id": "0b925a2d-944a-4f1d-a761-56d24db90341"
},
"muted_until": null,
"name": "test group",
"peer": null,
"room_id": "6eb71e13-fe76-4e5a-a9c2-6c197c5f1400",
"unread_count": 0
},
{
"description": "Saturday hike, then dinner at eight.",
"icon_attachment_id": null,
"kind": "group",
"last_message": {
"created_at": "2026-01-07T02:12:16Z",
"event_seq": 4689,
"kind": "system",
"preview": "system",
"sender_id": "4a98e767-a426-47e9-89a0-c499b54d2904"
},
"muted_until": null,
"name": "Weekend plans",
"peer": null,
"room_id": "aca2ceb1-e310-4e14-8882-d8e966b7d712",
"unread_count": 0
},
{
"description": "Saturday hike, then dinner at eight.",
"icon_attachment_id": null,
"kind": "group",
"last_message": {
"created_at": "2026-01-07T02:10:39Z",
"event_seq": 4680,
"kind": "system",
"preview": "system",
"sender_id": "4a98e767-a426-47e9-89a0-c499b54d2904"
},
"muted_until": null,
"name": "Weekend plans",
"peer": null,
"room_id": "b5e03d35-ea1d-403e-9a87-02e614aee58a",
"unread_count": 0
},
{
"description": null,
"icon_attachment_id": null,
"kind": "group",
"last_message": {
"created_at": "2026-01-04T08:56:33Z",
"event_seq": 4373,
"kind": "file",
"preview": "📎 File",
"sender_id": "0b925a2d-944a-4f1d-a761-56d24db90341"
},
"muted_until": null,
"name": "testing me",
"peer": null,
"room_id": "61f13be9-cf5b-4e1c-9d33-e39872d872c7",
"unread_count": 0
},
{
"description": null,
"icon_attachment_id": null,
"kind": "group",
"last_message": {
"created_at": "2026-01-03T07:42:03Z",
"event_seq": 4270,
"kind": "text",
"preview": "QA VERIFY 4",
"sender_id": "4a98e767-a426-47e9-89a0-c499b54d2904"
},
"muted_until": null,
"name": "Self Media Group",
"peer": null,
"room_id": "fadcd831-d379-493d-be50-222ecbf697e9",
"unread_count": 0
},
{
"description": null,
"icon_attachment_id": null,
"kind": "group",
"last_message": {
"created_at": "2026-01-02T08:38:19Z",
"event_seq": 4072,
"kind": "text",
"preview": "hyy",
"sender_id": "4a98e767-a426-47e9-89a0-c499b54d2904"
},
"muted_until": null,
"name": "Live Verify Group 1791189343212",
"peer": null,
"room_id": "9e052209-79c3-487b-9a5a-ad43bbceb481",
"unread_count": 0
},
{
"description": null,
"icon_attachment_id": null,
"kind": "direct",
"last_message": {
"created_at": "2025-12-26T17:24:59Z",
"event_seq": 3670,
"kind": "text",
"preview": "hi",
"sender_id": "4a98e767-a426-47e9-89a0-c499b54d2904"
},
"muted_until": null,
"name": null,
"peer": {
"avatar_version": null,
"display_name": null,
"phone": "+15550003333",
"user_id": "9b2f6052-edf8-424e-9c1a-ecd90a1607e4"
},
"room_id": "c8366e3b-a43d-4e20-91ef-567e1287e110",
"unread_count": 0
},
{
"description": null,
"icon_attachment_id": null,
"kind": "group",
"last_message": {
"created_at": "2025-12-26T15:02:18Z",
"event_seq": 3657,
"kind": "deleted",
"preview": "Message deleted",
"sender_id": "4a98e767-a426-47e9-89a0-c499b54d2904"
},
"muted_until": null,
"name": "sdfghjklllkjhgfdcvbhjklkmnbv",
"peer": null,
"room_id": "d4ac2357-7773-4840-b9ac-f4ebc7978267",
"unread_count": 0
},
{
"description": null,
"icon_attachment_id": null,
"kind": "group",
"last_message": null,
"muted_until": null,
"name": "Backend Test Grp",
"peer": null,
"room_id": "36bf8624-46f1-40a0-9ead-1b6ad5a1163f",
"unread_count": 0
},
{
"description": null,
"icon_attachment_id": null,
"kind": "group",
"last_message": {
"created_at": "2025-12-21T09:19:52Z",
"event_seq": 3293,
"kind": "text",
"preview": "ClearWatermarkProbe",
"sender_id": "0b925a2d-944a-4f1d-a761-56d24db90341"
},
"muted_until": null,
"name": "Group call",
"peer": null,
"room_id": "e23fb102-5878-4b14-a637-a6878a202935",
"unread_count": 0
},
{
"description": null,
"icon_attachment_id": null,
"kind": "group",
"last_message": null,
"muted_until": null,
"name": "TestGroup-1790159400517",
"peer": null,
"room_id": "4d55f4fa-516c-4ddc-8e08-18719784882d",
"unread_count": 0
},
{
"description": null,
"icon_attachment_id": null,
"kind": "group",
"last_message": null,
"muted_until": null,
"name": "Weekend plans",
"peer": null,
"room_id": "dc18e5c2-e264-4ead-be79-1f78faf15a54",
"unread_count": 0
},
{
"description": null,
"icon_attachment_id": null,
"kind": "group",
"last_message": null,
"muted_until": null,
"name": "QA Test Group",
"peer": null,
"room_id": "5e38f7cd-e6f7-428e-b3ec-1d57d6fc4025",
"unread_count": 0
},
{
"description": null,
"icon_attachment_id": null,
"kind": "group",
"last_message": null,
"muted_until": null,
"name": "QA Test Group",
"peer": null,
"room_id": "d7f66e06-79d0-4cd8-9f13-6795b4ac692f",
"unread_count": 0
},
{
"description": null,
"icon_attachment_id": null,
"kind": "group",
"last_message": null,
"muted_until": null,
"name": "Weekend plans",
"peer": null,
"room_id": "6c0db0aa-7c88-410c-bcf1-e0f17cbe0cdf",
"unread_count": 0
},
{
"description": null,
"icon_attachment_id": null,
"kind": "group",
"last_message": null,
"muted_until": null,
"name": "Weekend plans",
"peer": null,
"room_id": "ee286c5c-7607-453f-8165-8a40f3e19214",
"unread_count": 0
},
{
"description": null,
"icon_attachment_id": null,
"kind": "group",
"last_message": null,
"muted_until": null,
"name": "Weekend plans",
"peer": null,
"room_id": "a970b461-8d3c-4c2e-88c2-77beee06a75f",
"unread_count": 0
},
{
"description": null,
"icon_attachment_id": null,
"kind": "group",
"last_message": null,
"muted_until": null,
"name": "Weekend plans",
"peer": null,
"room_id": "07191895-7185-4474-b1fd-e804fc432f1a",
"unread_count": 0
},
{
"description": null,
"icon_attachment_id": null,
"kind": "group",
"last_message": null,
"muted_until": null,
"name": "Weekend plans",
"peer": null,
"room_id": "f9f4c84c-1028-46de-905b-214423a81304",
"unread_count": 0
}
]
} Response fields (19)
| Field | Type | Description |
|---|---|---|
conversations | array of object | The caller's conversations as a chat list, most recent activity first. |
conversations[]. | string (uuid) | The conversation's room. |
conversations[]. | one of: direct, group | direct or group. |
conversations[]. | string, nullable | The group's name; null for a direct conversation (use peer). |
conversations[]. | string, nullable max length 1024 | The group's description, up to 1024 characters; null when there is none. |
conversations[]. | string (uuid), nullable | The group's icon: an image attachment of the group's own room, or null. Fetch it like any picture posted there — GET /v1/rooms/{room_id}/attachments/{attachment_id}/download with a room token — and cache it by id; a changed icon is a new id. |
conversations[]. | object, nullable | For a direct conversation, the other person; null for a group. |
conversations[]. | string (uuid) | The other person's user id. |
conversations[]. | string, nullable | Their display name, or null. |
conversations[]. | string | Their phone number, E.164. |
conversations[]. | string (date-time), nullable | When the other person's current profile photo was set; null when there is none. The value to cache the picture by: fetch GET /v1/directory/users/{user_id}/avatar once per version (its ETag is this value). |
conversations[]. | integer | Messages after the caller's read cursor. |
conversations[]. | string (date-time), nullable | Until when you have muted this conversation; null when not muted (a lapsed mute reads as null). 9999-12-31T00:00:00Z stands for "until unmuted". Private: only your own mute is ever shown. |
conversations[]. | object, nullable | The newest message, for the preview line; null if the conversation has none. |
conversations[]. | integer | Its position in the room. |
conversations[]. | string, nullable | Who sent it. |
conversations[]. | string | Its kind. |
conversations[]. | string | A short label for the chat list: text up to 120 characters, or a label such as "📷 Photo" for media and "Message deleted" for a deleted message. |
conversations[]. | string (date-time), nullable | When it was sent. |
Errors · 401
| Status | When |
|---|---|
401 | Missing, expired or invalid credentials |
Group management #
A conversation as a member sees it: name, description, icon, size
Request
curl -X GET https://api.ollacore.com/v1/directory/conversations/60f99e3b-2084-4bb5-9adb-527ee9907673 \
-H "Authorization: Bearer du_…" | Parameter | Type | Description |
|---|---|---|
room_id path required | string (uuid) | The conversation. 404 if it is not a directory conversation of your tenant; 403 if you are not a member. |
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
{
"room_id": "60f99e3b-2084-4bb5-9adb-527ee9907673",
"kind": "group",
"name": "Weekend plans",
"description": null,
"icon_attachment_id": null,
"member_count": 2,
"created_at": "2026-01-15T09:30:44Z"
} Response fields (7)
| Field | Type | Description |
|---|---|---|
room_id required | string (uuid) | The conversation's room. |
kind required | one of: direct, group | direct or group. |
name required | string, nullable | The group's name; null for a direct conversation or an unnamed group. |
description required | string, nullable max length 1024 | The group's description, up to 1024 characters; null when there is none. |
icon_attachment_id required | string (uuid), nullable | The group's icon: an image attachment of the group's own room, or null. Fetch it like any picture posted there — GET /v1/rooms/{room_id}/attachments/{attachment_id}/download with a room token — and cache it by id; a changed icon is a new id. |
member_count required | integer | Active members. |
created_at required | string (date-time) | When the conversation was created. |
Errors · 401 · 403 · 404
| Status | When |
|---|---|
401 | Missing, expired or invalid credentials |
403 | Authenticated, but the token is not scoped to this room or principal |
404 | No such room, message, member or attachment |
Owner: rename a group, set its description or icon
Request
curl -X PATCH https://api.ollacore.com/v1/directory/conversations/60f99e3b-2084-4bb5-9adb-527ee9907673 \
-H "Authorization: Bearer du_…" \
-H "Content-Type: application/json" \
-d '{"name":"Weekend plans","description":"Saturday hike, then dinner at eight."}' {
"name": "Weekend plans",
"description": "Saturday hike, then dinner at eight."
} | Parameter | Type | Description |
|---|---|---|
room_id path required | string (uuid) | The group. 404 if it is not a directory conversation of your tenant; 403 if you are not a member; 403 if you are not its owner. |
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
| Field | Type | Description |
|---|---|---|
name | string, nullable max length 128 | The new name, up to 128 characters; null or empty clears it. |
description | string, nullable max length 1024 | The new description, up to 1024 characters; null or empty clears it. |
icon_attachment_id | string (uuid), nullable | A ready image attachment of this group's room, or null to remove the icon. |
Response · 200
{
"room_id": "60f99e3b-2084-4bb5-9adb-527ee9907673",
"kind": "group",
"name": "Weekend plans",
"description": "Saturday hike, then dinner at eight.",
"icon_attachment_id": null,
"member_count": 2,
"created_at": "2026-01-15T09:30:44Z"
} Response fields (7)
| Field | Type | Description |
|---|---|---|
room_id required | string (uuid) | The conversation's room. |
kind required | one of: direct, group | direct or group. |
name required | string, nullable | The group's name; null for a direct conversation or an unnamed group. |
description required | string, nullable max length 1024 | The group's description, up to 1024 characters; null when there is none. |
icon_attachment_id required | string (uuid), nullable | The group's icon: an image attachment of the group's own room, or null. Fetch it like any picture posted there — GET /v1/rooms/{room_id}/attachments/{attachment_id}/download with a room token — and cache it by id; a changed icon is a new id. |
member_count required | integer | Active members. |
created_at required | string (date-time) | When the conversation was created. |
Errors · 400 · 401 · 403 · 404
| Status | When |
|---|---|
400 | Nothing to update, a name over 128 or a description over 1024 characters, an icon_attachment_id that is not a ready image of this group, or a direct conversation. |
401 | Missing, expired or invalid credentials |
403 | Authenticated, but the token is not scoped to this room or principal |
404 | No such room, message, member or attachment |
Members, owners first
Request
curl -X GET https://api.ollacore.com/v1/directory/conversations/60f99e3b-2084-4bb5-9adb-527ee9907673/members \
-H "Authorization: Bearer du_…" | Parameter | Type | Description |
|---|---|---|
room_id path required | string (uuid) | The conversation. 404 if it is not a directory conversation of your tenant; 403 if you are not a member. |
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
{
"members": [
{
"about": "Ships things. Slow to reply at weekends.",
"avatar_version": "2026-01-15T09:30:44Z",
"display_name": "Alice Nakamura",
"joined_at": "2026-01-15T09:30:44Z",
"phone": "+15550001111",
"role": "owner",
"user_id": "4a98e767-a426-47e9-89a0-c499b54d2904"
},
{
"about": null,
"avatar_version": null,
"display_name": "malavika rajesh",
"joined_at": "2026-01-15T09:30:44Z",
"phone": "+15550002222",
"role": "member",
"user_id": "0b925a2d-944a-4f1d-a761-56d24db90341"
}
]
} Response fields (8)
| Field | Type | Description |
|---|---|---|
members | array of DirectoryGroupMember | |
members[]. required if its parent is sent | string (uuid) | The member's directory user id — also their principal id in the room. |
members[]. | string, nullable | As set on their profile, or null. |
members[]. required if its parent is sent | string | E.164. |
members[]. | string, nullable max length 256 | The profile line, up to 256 characters; null when not set. |
members[]. | string (date-time), nullable | When their current profile photo was set; null when there is none. The value to cache the picture by: fetch GET /v1/directory/users/{user_id}/avatar once per version (its ETag is this value). |
members[]. required if its parent is sent | one of: owner, member, viewer | owner manages the group; see the group-management operations. |
members[]. | string (date-time), nullable | When they first joined; a restored member keeps the original time. |
Errors · 401 · 403 · 404
| Status | When |
|---|---|
401 | Missing, expired or invalid credentials |
403 | Authenticated, but the token is not scoped to this room or principal |
404 | No such room, message, member or attachment |
Owner: add up to 256 members (409 once the room holds 5,000)
Request
curl -X POST https://api.ollacore.com/v1/directory/conversations/60f99e3b-2084-4bb5-9adb-527ee9907673/members \
-H "Authorization: Bearer du_…" \
-H "Content-Type: application/json" \
-d '{"member_user_ids":["0b925a2d-944a-4f1d-a761-56d24db90341"]}' {
"member_user_ids": [
"0b925a2d-944a-4f1d-a761-56d24db90341"
]
} | Parameter | Type | Description |
|---|---|---|
room_id path required | string (uuid) | The group. 404 if it is not a directory conversation of your tenant; 403 if you are not its owner; 400 if it is a direct conversation. |
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
| Field | Type | Description |
|---|---|---|
member_user_ids required | array of string (uuid) max 256 items | Who to add, 1–256 directory user ids. |
Response · 200
{
"added": [
"0b925a2d-944a-4f1d-a761-56d24db90341"
],
"member_count": 2,
"not_added": []
} Response fields (5)
| Field | Type | Description |
|---|---|---|
added | array of string (uuid) | The ids admitted by this call, in request order, without duplicates. |
member_count | integer | Active members after the call. |
not_added | array of NotAdded | People you named who were not added, with the reason — only blocked today: they have blocked you. Absent or empty when everyone was added. |
not_added[]. required if its parent is sent | string (uuid) | Someone you named who was not added. |
not_added[]. required if its parent is sent | one of: blocked | blocked: they have blocked you. |
Errors · 401 · 403 · 404 · 409
| Status | When |
|---|---|
401 | Missing, expired or invalid credentials |
403 | Authenticated, but the token is not scoped to this room or principal |
404 | No such room, message, member or attachment |
409 | Conflicts with current state |
Owner: make a member an owner, or an owner a member
Request
curl -X PUT https://api.ollacore.com/v1/directory/conversations/60f99e3b-2084-4bb5-9adb-527ee9907673/members/0b925a2d-944a-4f1d-a761-56d24db90341 \
-H "Authorization: Bearer du_…" \
-H "Content-Type: application/json" \
-d '{"role":"owner"}' {
"role": "owner"
} | Parameter | Type | Description |
|---|---|---|
room_id path required | string (uuid) | The group. 404 if it is not a directory conversation of your tenant; 403 if you are not a member; 403 if you are not an owner. |
user_id path required | string (uuid) | An active member of the group (404 otherwise); yourself included. |
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
| Field | Type | Description |
|---|---|---|
role required | one of: owner, member | The role to give. |
Response · 200
{
"role": "owner",
"user_id": "0b925a2d-944a-4f1d-a761-56d24db90341"
} Response fields (2)
| Field | Type | Description |
|---|---|---|
user_id required | string (uuid) | |
role required | one of: owner, member |
Errors · 400 · 401 · 403 · 404 · 409
| Status | When |
|---|---|
400 | A role other than owner or member, or a direct conversation. |
401 | Missing, expired or invalid credentials |
403 | Authenticated, but the token is not scoped to this room or principal |
404 | No such room, message, member or attachment |
409 | The member is the only owner. |
Owner: remove a member
Request
curl -X DELETE https://api.ollacore.com/v1/directory/conversations/60f99e3b-2084-4bb5-9adb-527ee9907673/members/0b925a2d-944a-4f1d-a761-56d24db90341 \
-H "Authorization: Bearer du_…" | Parameter | Type | Description |
|---|---|---|
room_id path required | string (uuid) | The group. 404 if it is not a directory conversation of your tenant; 403 if you are not its owner. |
user_id path required | string (uuid) | The member to remove. 404 if they are not an active member. |
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
{
"removed": true
} Response fields (1)
| Field | Type | Description |
|---|---|---|
removed | boolean |
Errors · 401 · 403 · 404
| Status | When |
|---|---|
401 | Missing, expired or invalid credentials |
403 | Authenticated, but the token is not scoped to this room or principal |
404 | No such room, message, member or attachment |
Leave a group; a lone owner's seat passes to the longest-standing member
Request
curl -X POST https://api.ollacore.com/v1/directory/conversations/60f99e3b-2084-4bb5-9adb-527ee9907673/leave \
-H "Authorization: Bearer du_…" | Parameter | Type | Description |
|---|---|---|
room_id path required | string (uuid) | The group. 404 if it is not a directory conversation of your tenant; 403 if you are not a member. |
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
{
"closed": false,
"left": true,
"new_owner": null
} Response fields (3)
| Field | Type | Description |
|---|---|---|
left | boolean | |
new_owner | string, nullable | The member who inherited ownership, or null. |
closed | boolean | True when you were the last member and the room closed. |
Errors · 401 · 403 · 404
| Status | When |
|---|---|
401 | Missing, expired or invalid credentials |
403 | Authenticated, but the token is not scoped to this room or principal |
404 | No such room, message, member or attachment |
Invite links #
Owner: create a link — the token is shown once
Request
curl -X POST https://api.ollacore.com/v1/directory/conversations/60f99e3b-2084-4bb5-9adb-527ee9907673/invites \
-H "Authorization: Bearer du_…" \
-H "Content-Type: application/json" \
-d '{"expires_in_seconds":86400,"max_uses":5}' {
"expires_in_seconds": 86400,
"max_uses": 5
} | Parameter | Type | Description |
|---|---|---|
room_id path required | string (uuid) | The group. 404 if it is not a directory conversation of your tenant; 403 if you are not a member; 403 if you are not an owner. |
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
| Field | Type | Description |
|---|---|---|
expires_in_seconds | integer (int64) min 1 · max 2592000 | Seconds until the link stops working; omitted means it does not expire. |
max_uses | integer min 1 | How many people may join through it; omitted means any number. |
Response · 200
{
"created_at": "2026-01-15T09:30:46Z",
"created_by": "4a98e767-a426-47e9-89a0-c499b54d2904",
"expires_at": "2026-01-16T09:30:46Z",
"invite_id": "e7a02742-30b8-40ec-aa18-85744bbac5d3",
"max_uses": 5,
"room_id": "60f99e3b-2084-4bb5-9adb-527ee9907673",
"token": "EXAMPLE_INVITE_TOKEN",
"uses": 0
} Response fields (8)
| Field | Type | Description |
|---|---|---|
invite_id required | string (uuid) | The link, for revoking it. |
room_id required | string (uuid) | The group it admits to. |
created_by required | string (uuid) | The owner who created it. |
created_at required | string (date-time) | |
expires_at required | string (date-time), nullable | When it stops working; null for a link that does not expire. |
max_uses required | integer, nullable | How many people may join through it; null for any number. |
uses required | integer | How many have. A member joining again is not a use. |
token required | string | The token to share (inv_ and 43 URL-safe characters). Shown only here. |
Errors · 400 · 401 · 403 · 404 · 409 · 429
| Status | When |
|---|---|
400 | expires_in_seconds outside 1..=2592000 or max_uses below 1. |
401 | Missing, expired or invalid credentials |
403 | Authenticated, but the token is not scoped to this room or principal |
404 | No such room, message, member or attachment |
409 | The group already holds 20 live links. |
429 | Rate limit exceeded |
Owner: live links, without tokens
Request
curl -X GET https://api.ollacore.com/v1/directory/conversations/60f99e3b-2084-4bb5-9adb-527ee9907673/invites \
-H "Authorization: Bearer du_…" | Parameter | Type | Description |
|---|---|---|
room_id path required | string (uuid) | The group. 404 if it is not a directory conversation of your tenant; 403 if you are not a member; 403 if you are not an owner. |
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
{
"invites": [
{
"created_at": "2026-01-15T09:30:46Z",
"created_by": "4a98e767-a426-47e9-89a0-c499b54d2904",
"expires_at": "2026-01-16T09:30:46Z",
"invite_id": "e7a02742-30b8-40ec-aa18-85744bbac5d3",
"max_uses": 5,
"room_id": "60f99e3b-2084-4bb5-9adb-527ee9907673",
"uses": 0
}
]
} Response fields (8)
| Field | Type | Description |
|---|---|---|
invites required | array of GroupInvite | |
invites[]. required | string (uuid) | The link, for revoking it. |
invites[]. required | string (uuid) | The group it admits to. |
invites[]. required | string (uuid) | The owner who created it. |
invites[]. required | string (date-time) | |
invites[]. required | string (date-time), nullable | When it stops working; null for a link that does not expire. |
invites[]. required | integer, nullable | How many people may join through it; null for any number. |
invites[]. required | integer | How many have. A member joining again is not a use. |
Errors · 401 · 403 · 404
| Status | When |
|---|---|
401 | Missing, expired or invalid credentials |
403 | Authenticated, but the token is not scoped to this room or principal |
404 | No such room, message, member or attachment |
Owner: revoke a link
Request
curl -X DELETE https://api.ollacore.com/v1/directory/conversations/60f99e3b-2084-4bb5-9adb-527ee9907673/invites/e7a02742-30b8-40ec-aa18-85744bbac5d3 \
-H "Authorization: Bearer du_…" | Parameter | Type | Description |
|---|---|---|
room_id path required | string (uuid) | The group. 404 if it is not a directory conversation of your tenant; 403 if you are not a member; 403 if you are not an owner. |
invite_id path required | string (uuid) | From inviteCreate or the list. |
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)
| Field | Type | Description |
|---|---|---|
revoked required | boolean |
Errors · 401 · 403 · 404
| Status | When |
|---|---|
401 | Missing, expired or invalid credentials |
403 | Authenticated, but the token is not scoped to this room or principal |
404 | No such room, message, member or attachment |
What a link leads to, before joining (token in the body)
Request
curl -X POST https://api.ollacore.com/v1/directory/invites/preview \
-H "Authorization: Bearer du_…" \
-H "Content-Type: application/json" \
-d '{"token":"EXAMPLE_INVITE_TOKEN"}' {
"token": "EXAMPLE_INVITE_TOKEN"
} | Parameter | Type | Description |
|---|---|---|
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
| Field | Type | Description |
|---|---|---|
token required | string | The link token, exactly as the owner received it (inv_…). |
Response · 200
{
"description": "Saturday hike, then dinner at eight.",
"expires_at": "2026-01-16T09:30:46Z",
"icon_attachment_id": null,
"member": false,
"member_count": 1,
"name": "Weekend plans",
"room_id": "60f99e3b-2084-4bb5-9adb-527ee9907673"
} Response fields (7)
| Field | Type | Description |
|---|---|---|
room_id required | string (uuid) | The group the link admits to. |
name required | string, nullable | |
description required | string, nullable max length 1024 | The group's description, up to 1024 characters; null when there is none. |
icon_attachment_id required | string (uuid), nullable | The group's icon, if any. A non-member cannot fetch it until they join; show it from the id once in. |
member_count required | integer | Active members. |
member required | boolean | Whether you are already in the group. |
expires_at required | string (date-time), nullable | When the link stops working; null for one that does not expire. |
Errors · 401 · 404 · 429
| Status | When |
|---|---|
401 | Missing, expired or invalid credentials |
404 | No such room, message, member or attachment |
429 | Rate limit exceeded |
Join a group through a link
Request
curl -X POST https://api.ollacore.com/v1/directory/invites/join \
-H "Authorization: Bearer du_…" \
-H "Content-Type: application/json" \
-d '{"token":"EXAMPLE_INVITE_TOKEN"}' {
"token": "EXAMPLE_INVITE_TOKEN"
} | Parameter | Type | Description |
|---|---|---|
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
| Field | Type | Description |
|---|---|---|
token required | string | The link token, exactly as the owner received it (inv_…). |
Response · 200
{
"joined": true,
"member_count": 2,
"room_id": "60f99e3b-2084-4bb5-9adb-527ee9907673"
} Response fields (3)
| Field | Type | Description |
|---|---|---|
room_id required | string (uuid) | The group. Mint a token for it to chat or call. |
joined required | boolean | False when you were already in. |
member_count required | integer | Active members after the call. |
Errors · 401 · 404 · 409 · 429
| Status | When |
|---|---|
401 | Missing, expired or invalid credentials |
404 | No such room, message, member or attachment |
409 | The group is full (5,000 members). |
429 | Rate limit exceeded |
Mute & block #
Silence this conversation's push for yourself — 8h, 1w or always
Request
curl -X PUT https://api.ollacore.com/v1/directory/conversations/eb0a0da1-5344-483f-8b18-b95bfc4d1e36/mute \
-H "Authorization: Bearer du_…" \
-H "Content-Type: application/json" \
-d '{"duration":"1w"}' {
"duration": "1w"
} | Parameter | Type | Description |
|---|---|---|
room_id path required | string (uuid) | The conversation, direct or group. 404 if it is not a directory conversation of your tenant; 403 if you are not a member. |
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
| Field | Type | Description |
|---|---|---|
duration required | one of: 8h, 1w, always | How long to silence push notifications: eight hours, one week, or until unmuted. 9999-12-31T00:00:00Z stands for "until unmuted". |
Response · 200
{
"muted_until": "2026-01-22T09:30:47Z",
"room_id": "eb0a0da1-5344-483f-8b18-b95bfc4d1e36"
} Response fields (2)
| Field | Type | Description |
|---|---|---|
room_id required | string (uuid) | The conversation. |
muted_until required | string (date-time), nullable | Until when push notifications from this conversation are silenced for you; null when not muted. 9999-12-31T00:00:00Z stands for "until unmuted". |
Errors · 401 · 403 · 404 · 422
| Status | When |
|---|---|
401 | Missing, expired or invalid credentials |
403 | Authenticated, but the token is not scoped to this room or principal |
404 | No such room, message, member or attachment |
422 | A duration outside 8h|1w|always, or an unknown field. |
Unmute
Request
curl -X DELETE https://api.ollacore.com/v1/directory/conversations/eb0a0da1-5344-483f-8b18-b95bfc4d1e36/mute \
-H "Authorization: Bearer du_…" | Parameter | Type | Description |
|---|---|---|
room_id path required | string (uuid) | The conversation, direct or group. 404 if it is not a directory conversation of your tenant; 403 if you are not a member. |
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
{
"muted_until": null,
"room_id": "eb0a0da1-5344-483f-8b18-b95bfc4d1e36"
} Response fields (2)
| Field | Type | Description |
|---|---|---|
room_id required | string (uuid) | The conversation. |
muted_until required | string (date-time), nullable | Until when push notifications from this conversation are silenced for you; null when not muted. 9999-12-31T00:00:00Z stands for "until unmuted". |
Errors · 401 · 403 · 404
| Status | When |
|---|---|
401 | Missing, expired or invalid credentials |
403 | Authenticated, but the token is not scoped to this room or principal |
404 | No such room, message, member or attachment |
Your block list
Request
curl -X GET https://api.ollacore.com/v1/directory/blocks \
-H "Authorization: Bearer du_…" | Parameter | Type | Description |
|---|---|---|
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
{
"blocks": [
{
"display_name": "malavika rajesh",
"phone": "+15550002222",
"since": "2026-01-15T09:30:47Z",
"user_id": "0b925a2d-944a-4f1d-a761-56d24db90341"
}
]
} Response fields (5)
| Field | Type | Description |
|---|---|---|
blocks required | array of BlockEntry | |
blocks[]. required | string (uuid) | The blocked user. |
blocks[]. required | string, nullable | Their display name, or null. |
blocks[]. required | string | Their phone number, E.164. |
blocks[]. required | string (date-time) | When you blocked them. |
Errors · 401
| Status | When |
|---|---|
401 | Missing, expired or invalid credentials |
Block a user — the direct chat freezes for both
Request
curl -X PUT https://api.ollacore.com/v1/directory/blocks/0b925a2d-944a-4f1d-a761-56d24db90341 \
-H "Authorization: Bearer du_…" | Parameter | Type | Description |
|---|---|---|
user_id path required | string (uuid) | A directory user of your tenant. |
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
{
"blocked": true,
"since": "2026-01-15T09:30:47Z",
"user_id": "0b925a2d-944a-4f1d-a761-56d24db90341"
} Response fields (3)
| Field | Type | Description |
|---|---|---|
user_id required | string (uuid) | |
blocked required | boolean | |
since | string (date-time) | When the block was placed; present when blocked is true. Blocking again keeps the original time. |
Errors · 400 · 401 · 404 · 409 · 429
| Status | When |
|---|---|
400 | You cannot block yourself. |
401 | Missing, expired or invalid credentials |
404 | No such room, message, member or attachment |
409 | Your block list is full (1,000 users). |
429 | Rate limit exceeded |
Unblock
Request
curl -X DELETE https://api.ollacore.com/v1/directory/blocks/0b925a2d-944a-4f1d-a761-56d24db90341 \
-H "Authorization: Bearer du_…" | Parameter | Type | Description |
|---|---|---|
user_id path required | string (uuid) | A directory user of your tenant. |
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
{
"blocked": false,
"user_id": "0b925a2d-944a-4f1d-a761-56d24db90341"
} Response fields (3)
| Field | Type | Description |
|---|---|---|
user_id required | string (uuid) | |
blocked required | boolean | |
since | string (date-time) | When the block was placed; present when blocked is true. Blocking again keeps the original time. |
Errors · 401 · 429
| Status | When |
|---|---|
401 | Missing, expired or invalid credentials |
429 | Rate limit exceeded |
Devices #
Register a push token
Request
curl -X POST https://api.ollacore.com/v1/directory/devices \
-H "Authorization: Bearer du_…" \
-H "Content-Type: application/json" \
-d '{"platform":"fcm","push_token":"EXAMPLE_DEVICE_PUSH_TOKEN"}' {
"platform": "fcm",
"push_token": "EXAMPLE_DEVICE_PUSH_TOKEN"
} | Parameter | Type | Description |
|---|---|---|
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
| Field | Type | Description |
|---|---|---|
platform required | one of: fcm, apns, web | fcm (Android), apns (iOS) or web. The backend sends native pushes to fcm and apns tokens. |
push_token required | string max length 4096 | The device's push token, up to 4096 characters. Registering the same token again refreshes it. |
Response · 200
{
"id": "fa01a2a6-4fd1-48e7-a18c-9bf7719f01b7",
"platform": "fcm",
"push_token": "EXAMPLE_DEVICE_PUSH_TOKEN",
"app_id": "da_3a0a2cfaabd34b7dbfb4ecd5033b0c5f",
"updated_at": "2026-01-15T09:30:44Z"
} Response fields (5)
| Field | Type | Description |
|---|---|---|
id | string (uuid) | The device registration's id. |
platform | string | The platform as stored. |
push_token | string | The token as stored. |
app_id | string, nullable | The directory app this token was registered under — selects the FCM/APNs credentials used to reach it. |
updated_at | string (date-time) | When it was registered or refreshed. |
Errors · 401
| Status | When |
|---|---|
401 | Missing, expired or invalid credentials |
List devices
Request
curl -X GET https://api.ollacore.com/v1/directory/devices \
-H "Authorization: Bearer du_…" | Parameter | Type | Description |
|---|---|---|
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
{
"devices": [
{
"app_id": "da_3a0a2cfaabd34b7dbfb4ecd5033b0c5f",
"id": "fa01a2a6-4fd1-48e7-a18c-9bf7719f01b7",
"platform": "fcm",
"push_token": "EXAMPLE_DEVICE_PUSH_TOKEN",
"updated_at": "2026-01-15T09:30:44Z"
}
]
} Response fields (6)
| Field | Type | Description |
|---|---|---|
devices | array of object | The caller's registered push devices. |
devices[]. | string (uuid) | The device registration's id. |
devices[]. | string | fcm, apns or web. |
devices[]. | string | The registered push token. |
devices[]. | string, nullable | The directory app this token was registered under — selects the FCM/APNs credentials used to reach it. Null for tokens registered before per-app credentials existed. |
devices[]. | string (date-time) | When the token was last registered or refreshed. |
Errors · 401
| Status | When |
|---|---|
401 | Missing, expired or invalid credentials |
Unregister a push token
Request
curl -X DELETE https://api.ollacore.com/v1/directory/devices \
-H "Authorization: Bearer du_…" \
-H "Content-Type: application/json" \
-d '{"push_token":"EXAMPLE_DEVICE_PUSH_TOKEN"}' {
"push_token": "EXAMPLE_DEVICE_PUSH_TOKEN"
} | Parameter | Type | Description |
|---|---|---|
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
| Field | Type | Description |
|---|---|---|
push_token required | string | The token to unregister. Call this on sign-out. |
Response · 200
{
"deleted": true
} Response fields (1)
| Field | Type | Description |
|---|---|---|
deleted | boolean | True if the token was registered to the caller and is now removed. |
Errors · 401 · 404
| Status | When |
|---|---|
401 | Missing, expired or invalid credentials |
404 | No 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 · a du_ directory session is required here
{
"code": "unauthorized",
"message": "unauthorized: not a directory session token"
} The full code list and retry guidance is on Errors & rate limits.