Organization
The org, its settings and its monthly usage.
Read the organization
/api/v1/orgThe caller's org: its name, its members by role, and this month's matches against its allowance. The org comes from the caller's own membership, never from input.
An API key carrying the scope named here, or a signed-in session.
- Scope
org:read- Key kinds
- Organization
Required and optional fields, allowed values and errors, as the page shows them.
Examples
curl "https://liviamatch.com/api/v1/org" \
-H "Authorization: Bearer $LIVIA_API_KEY"Responses
The org.
{
"data": {
"id": "b7c2e9a1-4d63-4f85-9e0a-2a1c8d3b5f76",
"name": "Hearth & Key Realty",
"members": [
{
"id": "3a8d1e47-9c52-4b0f-a6d3-5e7b2c9f1a04",
"name": "Harper Quinn",
"email": "harper@hearthandkey.example",
"role": "admin",
"joinedAt": "2026-08-14T09:30:00.000Z"
},
{
"id": "e1a5c8d2-6f37-4b94-a0c1-8d2e4f6a9b13",
"name": "Dev Patel",
"email": "dev@hearthandkey.example",
"role": "member",
"joinedAt": "2026-09-02T13:05:00.000Z"
}
],
"usage": {
"used": 38,
"allowance": 200,
"period": "2026-10"
}
}
}Fields (13)
| Field | Type | Description |
|---|---|---|
data | object | |
data.id | string (uuid) | |
data.name | string | null | |
data.members | object[] | |
data.members[].id | string (uuid) | |
data.members[].name | string | null | |
data.members[].email | string | |
data.members[].role | "owner" | "admin" | "member" | |
data.members[].joinedAt | string (date-time) | |
data.usage | object | |
data.usage.used | integer | Matches started this month. |
data.usage.allowance | integer | Matches the org may start this month. |
data.usage.period | string | The UTC month, 2026-10. |
Errors
Any call of this kind can also answer401 unauthenticated401 invalid-api-key403 insufficient-scope429 rate-limited429 monthly-cap-reached500 internal
Read this month's usage
/api/v1/org/usageMatches against the pool per person with each person's limit, and per API key. Admins only.
The AI tokens and dollars behind them, per person, per key and in total, live apart from stand-ins, are Livia staff's: each ai is in the answer only when the key's maker is Livia staff.
An API key carrying the scope named here, or a signed-in session.
- Scope
org:read- Key kinds
- Organization
- Access
- The caller must administer the organization.
Required and optional fields, allowed values and errors, as the page shows them.
Examples
curl "https://liviamatch.com/api/v1/org/usage" \
-H "Authorization: Bearer $LIVIA_API_KEY"Responses
The month's usage.
{
"data": {
"period": "2026-10",
"pool": {
"used": 38,
"allowance": 200
},
"defaultLimit": 60,
"people": [
{
"id": "3a8d1e47-9c52-4b0f-a6d3-5e7b2c9f1a04",
"email": "harper@hearthandkey.example",
"name": "Harper Quinn",
"role": "admin",
"member": true,
"matches": 31,
"runs": 31,
"limit": 60,
"limitFrom": "default",
"lastMatchAt": "2026-10-02T14:03:12.118Z",
"lastRunAt": "2026-10-02T14:03:12.118Z"
},
{
"id": "e1a5c8d2-6f37-4b94-a0c1-8d2e4f6a9b13",
"email": "dev@hearthandkey.example",
"name": "Dev Patel",
"role": "member",
"member": true,
"matches": 7,
"runs": 7,
"limit": 20,
"limitFrom": "person",
"lastMatchAt": "2026-10-01T10:44:51.002Z",
"lastRunAt": "2026-10-01T10:44:51.002Z"
}
],
"keys": [
{
"id": "2f9b6d41-8e03-4c75-b1a8-4c6e0d2f7a59",
"name": "crm-search",
"kind": "personal",
"madeBy": {
"id": "3a8d1e47-9c52-4b0f-a6d3-5e7b2c9f1a04",
"email": "harper@hearthandkey.example"
},
"matches": 12,
"runs": 12
}
]
}
}Fields (60)
| Field | Type | Description |
|---|---|---|
data | object | |
data.period | string | |
data.pool | object | |
data.pool.used | integer | |
data.pool.allowance | integer | |
data.defaultLimit | integer | null | |
data.people | object[] | |
data.people[].id | string (uuid) | |
data.people[].email | string | null | |
data.people[].name | string | null | |
data.people[].role | "owner" | "admin" | "member" | null | Null for someone who has left the org this month. |
data.people[].member | boolean | |
data.people[].matches | integer | The old name for runs, with the same count. |
data.people[].runs | integer | Runs this person started this month. |
data.people[].limit | integer | null | |
data.people[].limitFrom | string | null | Where the limit comes from: their own setting or the org default. |
data.people[].lastMatchAt | string (date-time) | null | The old name for lastRunAt, with the same instant. |
data.people[].lastRunAt | string (date-time) | null | When they last started a run; null if never. |
data.people[].ai | object, optional | Livia staff only. The AI calls behind this person's runs: tokens and dollars. Omitted unless the caller, or the key's maker, is Livia staff. |
data.people[].ai.live | object | Real provider calls and their dollars. |
data.people[].ai.live.calls | integer | |
data.people[].ai.live.inputTokens | number | null | |
data.people[].ai.live.outputTokens | number | null | |
data.people[].ai.live.costUsd | number | null | |
data.people[].ai.mock | object | Stand-in calls. Their dollars are a projection and never a charge. |
data.people[].ai.mock.calls | integer | |
data.people[].ai.mock.inputTokens | number | null | |
data.people[].ai.mock.outputTokens | number | null | |
data.people[].ai.mock.projectedCostUsd | number | null | |
data.keys | object[] | |
data.keys[].id | string (uuid) | |
data.keys[].name | string | |
data.keys[].kind | string | |
data.keys[].madeBy | object | |
data.keys[].madeBy.id | string (uuid) | |
data.keys[].madeBy.email | string | |
data.keys[].matches | integer | The old name for runs, with the same count. |
data.keys[].runs | integer | Runs started with this key this month. |
data.keys[].ai | object, optional | Livia staff only. The AI calls behind this key's runs: tokens and dollars. Omitted unless the caller, or the key's maker, is Livia staff. |
data.keys[].ai.live | object | Real provider calls and their dollars. |
data.keys[].ai.live.calls | integer | |
data.keys[].ai.live.inputTokens | number | null | |
data.keys[].ai.live.outputTokens | number | null | |
data.keys[].ai.live.costUsd | number | null | |
data.keys[].ai.mock | object | Stand-in calls. Their dollars are a projection and never a charge. |
data.keys[].ai.mock.calls | integer | |
data.keys[].ai.mock.inputTokens | number | null | |
data.keys[].ai.mock.outputTokens | number | null | |
data.keys[].ai.mock.projectedCostUsd | number | null | |
data.ai | object, optional | Livia staff only. The org's AI calls this month: tokens and dollars. Omitted unless the caller, or the key's maker, is Livia staff. |
data.ai.live | object | Real provider calls and their dollars. |
data.ai.live.calls | integer | |
data.ai.live.inputTokens | number | null | |
data.ai.live.outputTokens | number | null | |
data.ai.live.costUsd | number | null | |
data.ai.mock | object | Stand-in calls. Their dollars are a projection and never a charge. |
data.ai.mock.calls | integer | |
data.ai.mock.inputTokens | number | null | |
data.ai.mock.outputTokens | number | null | |
data.ai.mock.projectedCostUsd | number | null |
Errors
| Status | Code | When |
|---|---|---|
| 403 | forbidden | The caller does not administer the org. |
Any call of this kind can also answer401 unauthenticated401 invalid-api-key403 insufficient-scope429 rate-limited429 monthly-cap-reached500 internal
Change the organization's settings
/api/v1/orgChanges any of the org's name, brand policy, client sign-in by code and default monthly limit; send at least one. Each change is applied in turn and recorded in the trail. The name and the limit are checked first, so a refusal lands before anything is written.
An API key carrying the scope named here, or a signed-in session.
- Scope
org:write- Key kinds
- Organization
- Access
- The caller must administer the organization.
Required and optional fields, allowed values and errors, as the page shows them.
Request body
Any of the settings; at least one.
Fields (4)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Optional | The org's name: 1 to 120 characters once trimmed. |
brandPolicy | "default" | "enforced" | Optional | default lets people use their own brand kit; enforced makes everyone wear the org's. |
clientCodes | boolean | Optional | Whether clients may sign in with an access code as well as an emailed link. Turning it off ends every code session on its next request. |
defaultLimit | number | null | Optional | Matches a month each member gets unless given their own limit: a whole number from 0 to 100000, or null for none. 0 pauses everyone. |
{
"name": "Hearth & Key Realty",
"defaultLimit": 60
}Examples
curl -X PATCH "https://liviamatch.com/api/v1/org" \
-H "Authorization: Bearer $LIVIA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Hearth & Key Realty",
"defaultLimit": 60
}'Responses
The settings after the change.
{
"data": {
"id": "b7c2e9a1-4d63-4f85-9e0a-2a1c8d3b5f76",
"name": "Hearth & Key Realty",
"brandPolicy": "default",
"clientCodes": false,
"defaultLimit": 60
}
}Fields (6)
| Field | Type | Description |
|---|---|---|
data | object | |
data.id | string (uuid) | |
data.name | string | null | |
data.brandPolicy | "enforced" | "default" | "free" | |
data.clientCodes | boolean | Whether clients may sign in with an access code as well as an emailed link. |
data.defaultLimit | integer | null | Matches a month each member gets unless given their own; null is no default limit. |
Errors
| Status | Code | When |
|---|---|---|
| 403 | forbidden | The caller does not administer the org. |
| 400 | invalid | The body failed validation; issues names each field. |
| 400 | invalid-json | The body is empty or not JSON. |
Any call of this kind can also answer401 unauthenticated401 invalid-api-key403 insufficient-scope429 rate-limited429 monthly-cap-reached500 internal