{"openapi":"3.1.0","info":{"title":"Nolmo API","description":"Another system works with a Nolmo workspace the way a person does, within what an admin lets its key do. Make a key in Settings, API keys, and send it as `Authorization: Bearer <key>`. Start with [the guides](https://nolmo.no/developers).","version":"1.0.0"},"servers":[{"url":"https://api.nolmo.no"}],"paths":{"/v1/webhook-endpoints":{"get":{"tags":["Webhooks"],"summary":"List webhook endpoints","description":"The endpoints this key could have made: all of the workspace's when the key sees every group, otherwise those that hear only groups the key sees.","operationId":"list_endpoints_v1_webhook_endpoints_get","security":[{"HTTPBearer":[]}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointList"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope `webhooks:manage`, or the groups","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such endpoint, or one the key could not have made","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"The endpoint is off, or the workspace is at its limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Not accepted, e.g. `webhook_url_refused` (see `details.reason`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"tags":["Webhooks"],"summary":"Make a webhook endpoint","description":"Nolmo sends the chosen events to `url` as signed POSTs (see the `webhooks` section for the body and the signature). The address must be https and public; it is checked now and on every send. The answer holds the signing `secret`: **it is shown only here**.\n\nAn endpoint hears only the cases a key with its groups could read. A key can give only the groups it sees itself; `all_groups` needs a key that sees every group.","operationId":"create_endpoint_v1_webhook_endpoints_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"A value you make up, such as a UUID, for this one request. Send the same key again, after a timeout or a crash, and you get the first answer back (`Idempotent-Replayed: true`) and nothing is written twice. The same key with another body is 422 `idempotency_key_reused`. Kept for 24 hours","examples":["7c9e6679-7425-40de-944b-e07fc1f90ae7"],"title":"Idempotency-Key"},"description":"A value you make up, such as a UUID, for this one request. Send the same key again, after a timeout or a crash, and you get the first answer back (`Idempotent-Replayed: true`) and nothing is written twice. The same key with another body is 422 `idempotency_key_reused`. Kept for 24 hours"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointCreated"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope `webhooks:manage`, or the groups","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such endpoint, or one the key could not have made","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"The endpoint is off, or the workspace is at its limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Not accepted, e.g. `webhook_url_refused` (see `details.reason`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/webhook-endpoints/{endpoint_id}":{"get":{"tags":["Webhooks"],"summary":"Read a webhook endpoint","description":"The endpoint's address, events, groups and state. The secret is never returned.","operationId":"get_endpoint_v1_webhook_endpoints__endpoint_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","description":"The webhook endpoint's id","title":"Endpoint Id"},"description":"The webhook endpoint's id"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpoint"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope `webhooks:manage`, or the groups","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such endpoint, or one the key could not have made","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"The endpoint is off, or the workspace is at its limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Not accepted, e.g. `webhook_url_refused` (see `details.reason`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"tags":["Webhooks"],"summary":"Change a webhook endpoint","description":"Only what is sent changes. `enabled: true` turns a stopped endpoint on again and sends what waited, as long as it is within 24 hours.","operationId":"update_endpoint_v1_webhook_endpoints__endpoint_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","description":"The webhook endpoint's id","title":"Endpoint Id"},"description":"The webhook endpoint's id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpoint"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope `webhooks:manage`, or the groups","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such endpoint, or one the key could not have made","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"The endpoint is off, or the workspace is at its limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Not accepted, e.g. `webhook_url_refused` (see `details.reason`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"tags":["Webhooks"],"summary":"Delete a webhook endpoint","description":"The endpoint and its delivery log are gone, and nothing more is sent to it.","operationId":"delete_endpoint_v1_webhook_endpoints__endpoint_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","description":"The webhook endpoint's id","title":"Endpoint Id"},"description":"The webhook endpoint's id"}],"responses":{"204":{"description":"Successful Response"},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope `webhooks:manage`, or the groups","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such endpoint, or one the key could not have made","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"The endpoint is off, or the workspace is at its limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Not accepted, e.g. `webhook_url_refused` (see `details.reason`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/webhook-endpoints/{endpoint_id}/rotate-secret":{"post":{"tags":["Webhooks"],"summary":"Rotate an endpoint's secret","description":"A new secret, shown only in this answer. The old one keeps signing for 24 hours beside it (`webhook-signature` then holds both), so the receiver can change over without a gap.","operationId":"rotate_secret_v1_webhook_endpoints__endpoint_id__rotate_secret_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","description":"The webhook endpoint's id","title":"Endpoint Id"},"description":"The webhook endpoint's id"},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"A value you make up, such as a UUID, for this one request. Send the same key again, after a timeout or a crash, and you get the first answer back (`Idempotent-Replayed: true`) and nothing is written twice. The same key with another body is 422 `idempotency_key_reused`. Kept for 24 hours","examples":["7c9e6679-7425-40de-944b-e07fc1f90ae7"],"title":"Idempotency-Key"},"description":"A value you make up, such as a UUID, for this one request. Send the same key again, after a timeout or a crash, and you get the first answer back (`Idempotent-Replayed: true`) and nothing is written twice. The same key with another body is 422 `idempotency_key_reused`. Kept for 24 hours"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointCreated"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope `webhooks:manage`, or the groups","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such endpoint, or one the key could not have made","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"The endpoint is off, or the workspace is at its limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Not accepted, e.g. `webhook_url_refused` (see `details.reason`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/webhook-endpoints/{endpoint_id}/deliveries":{"get":{"tags":["Webhooks"],"summary":"The delivery log","description":"What was sent to the endpoint in the last 30 days, newest first: the event, how many attempts, the receiver's last status code. Page with `cursor`.","operationId":"list_deliveries_v1_webhook_endpoints__endpoint_id__deliveries_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","description":"The webhook endpoint's id","title":"Endpoint Id"},"description":"The webhook endpoint's id"},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"`next_cursor` of the previous page","title":"Cursor"},"description":"`next_cursor` of the previous page"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"description":"How many deliveries to return","default":50,"title":"Limit"},"description":"How many deliveries to return"},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"enum":["pending","delivered","failed"],"type":"string"},{"type":"null"}],"description":"Only deliveries in this state","title":"Status"},"description":"Only deliveries in this state"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDeliveryList"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope `webhooks:manage`, or the groups","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such endpoint, or one the key could not have made","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"The endpoint is off, or the workspace is at its limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Not accepted, e.g. `webhook_url_refused` (see `details.reason`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/webhook-endpoints/{endpoint_id}/deliveries/{delivery_id}/resend":{"post":{"tags":["Webhooks"],"summary":"Send one event again","description":"The same event with the same `webhook-id`, as a new series of attempts. The receiver dedupes by that id.","operationId":"resend_delivery_v1_webhook_endpoints__endpoint_id__deliveries__delivery_id__resend_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","description":"The webhook endpoint's id","title":"Endpoint Id"},"description":"The webhook endpoint's id"},{"name":"delivery_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","description":"The delivery's id, as the receiver got it in `webhook-id`","title":"Delivery Id"},"description":"The delivery's id, as the receiver got it in `webhook-id`"},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"A value you make up, such as a UUID, for this one request. Send the same key again, after a timeout or a crash, and you get the first answer back (`Idempotent-Replayed: true`) and nothing is written twice. The same key with another body is 422 `idempotency_key_reused`. Kept for 24 hours","examples":["7c9e6679-7425-40de-944b-e07fc1f90ae7"],"title":"Idempotency-Key"},"description":"A value you make up, such as a UUID, for this one request. Send the same key again, after a timeout or a crash, and you get the first answer back (`Idempotent-Replayed: true`) and nothing is written twice. The same key with another body is 422 `idempotency_key_reused`. Kept for 24 hours"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDelivery"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope `webhooks:manage`, or the groups","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such endpoint, or one the key could not have made","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"The endpoint is off, or the workspace is at its limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Not accepted, e.g. `webhook_url_refused` (see `details.reason`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/webhook-endpoints/{endpoint_id}/replay":{"post":{"tags":["Webhooks"],"summary":"Send everything since a time again","description":"Every event in the log since `since`, delivered or not, again and in order, each with its own `webhook-id`. For a receiver that was down for longer than the 24 hours events are retried. Only the last 30 days are kept.","operationId":"replay_v1_webhook_endpoints__endpoint_id__replay_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","description":"The webhook endpoint's id","title":"Endpoint Id"},"description":"The webhook endpoint's id"},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"A value you make up, such as a UUID, for this one request. Send the same key again, after a timeout or a crash, and you get the first answer back (`Idempotent-Replayed: true`) and nothing is written twice. The same key with another body is 422 `idempotency_key_reused`. Kept for 24 hours","examples":["7c9e6679-7425-40de-944b-e07fc1f90ae7"],"title":"Idempotency-Key"},"description":"A value you make up, such as a UUID, for this one request. Send the same key again, after a timeout or a crash, and you get the first answer back (`Idempotent-Replayed: true`) and nothing is written twice. The same key with another body is 422 `idempotency_key_reused`. Kept for 24 hours"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Replay"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Replayed"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope `webhooks:manage`, or the groups","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such endpoint, or one the key could not have made","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"The endpoint is off, or the workspace is at its limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Not accepted, e.g. `webhook_url_refused` (see `details.reason`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/me":{"get":{"tags":["Account"],"summary":"Who is calling","description":"The key's name, workspace, scopes and groups. Every answer carries `RateLimit-Limit`,\n`RateLimit-Remaining` and `RateLimit-Reset`.","operationId":"me_v1_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Me"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/cases/search":{"get":{"tags":["Cases"],"summary":"Search cases","description":"Find cases by what was said in them, from the cases the key sees. A case in a group the key does\nnot see is never found, with or without a filter.\n\nThis is the app's own search, so the inbox and the API find the same cases. Searching the team's\ninternal notes too is opt-in with `include_notes`. Page with `after`, as with `GET /v1/cases`.","operationId":"search_cases_v1_cases_search_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":200,"description":"What to look for: words from the subject or a message, or a case number","examples":["cracked tiles"],"title":"Q"},"description":"What to look for: words from the subject or a message, or a case number"},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"enum":["new","open","pending","hold","solved","closed"],"type":"string"}},{"type":"null"}],"description":"Only cases in these statuses","title":"Status"},"description":"Only cases in these statuses"},{"name":"priority","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"enum":["low","normal","high","urgent"],"type":"string"}},{"type":"null"}],"description":"Only cases with these priorities","title":"Priority"},"description":"Only cases with these priorities"},{"name":"type","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Only cases of these types, by key (`GET /v1/case-types`)","examples":[["return"]],"title":"Type"},"description":"Only cases of these types, by key (`GET /v1/case-types`)"},{"name":"group_id","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Only cases in these groups (`GET /v1/groups`); `none` is the cases with no group","examples":[["0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6"]],"title":"Group Id"},"description":"Only cases in these groups (`GET /v1/groups`); `none` is the cases with no group"},{"name":"assignee_id","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Only cases assigned to these people (`GET /v1/agents`); `none` is the unassigned","examples":[["0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6"]],"title":"Assignee Id"},"description":"Only cases assigned to these people (`GET /v1/agents`); `none` is the unassigned"},{"name":"tag","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Only cases with every one of these tags","examples":[["delivery"]],"title":"Tag"},"description":"Only cases with every one of these tags"},{"name":"channel","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Only cases that arrived on these channels","examples":[["email","api"]],"title":"Channel"},"description":"Only cases that arrived on these channels"},{"name":"created_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Created at or after this time","examples":["2026-11-01T00:00:00Z"],"title":"Created From"},"description":"Created at or after this time"},{"name":"created_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Created before this time","examples":["2026-12-01T00:00:00Z"],"title":"Created To"},"description":"Created before this time"},{"name":"updated_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Updated at or after this time","examples":["2026-11-01T00:00:00Z"],"title":"Updated From"},"description":"Updated at or after this time"},{"name":"updated_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Updated before this time","examples":["2026-12-01T00:00:00Z"],"title":"Updated To"},"description":"Updated before this time"},{"name":"include_notes","in":"query","required":false,"schema":{"type":"boolean","description":"Also count the team's internal notes, which are left out unless you ask for them","default":false,"title":"Include Notes"},"description":"Also count the team's internal notes, which are left out unless you ask for them"},{"name":"after","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The `next_cursor` of the previous page; leave out for the first","examples":["eyJ2Ijog"],"title":"After"},"description":"The `next_cursor` of the previous page; leave out for the first"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"description":"How many to return, at most","default":50,"title":"Limit"},"description":"How many to return, at most"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseList"}}}},"400":{"description":"A filter is not an id, or the cursor is not one this API issued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope `cases:read`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The request did not validate","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/cases/{number}/attachments":{"get":{"tags":["Cases"],"summary":"List a case's files","description":"The files on the case's messages, oldest first, a page at a time. Files on the team's internal notes\nare left out unless `include_notes` is true. Download one with `GET /v1/attachments/{id}`.","operationId":"list_case_files_v1_cases__number__attachments_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"number","in":"path","required":true,"schema":{"type":"integer","description":"The case's number in the workspace","examples":[1042],"title":"Number"},"description":"The case's number in the workspace"},{"name":"include_notes","in":"query","required":false,"schema":{"type":"boolean","description":"Also count the team's internal notes, which are left out unless you ask for them","default":false,"title":"Include Notes"},"description":"Also count the team's internal notes, which are left out unless you ask for them"},{"name":"after","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The `next_cursor` of the previous page; leave out for the first","examples":["eyJ2Ijog"],"title":"After"},"description":"The `next_cursor` of the previous page; leave out for the first"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"description":"About how many files to return; a message's files stay together","default":100,"title":"Limit"},"description":"About how many files to return; a message's files stay together"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseFileList"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope `cases:read`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such case or file, or one in a group the key does not see","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The request did not validate","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/attachments/{attachment_id}":{"get":{"tags":["Cases"],"summary":"Download a file","description":"The file, or a redirect (307) to a signed address that lives for a few minutes and carries no key;\nfollow it without sending your `Authorization` header on. A file on a case the key does not see, a\nfile on an internal note (unless `include_notes` is true) and an id that does not exist are the same\n404.","operationId":"download_file_v1_attachments__attachment_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"attachment_id","in":"path","required":true,"schema":{"type":"string","description":"The file's `id` from `GET /v1/cases/{number}/attachments`","examples":["0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6"],"title":"Attachment Id"},"description":"The file's `id` from `GET /v1/cases/{number}/attachments`"},{"name":"include_notes","in":"query","required":false,"schema":{"type":"boolean","description":"Also count the team's internal notes, which are left out unless you ask for them","default":false,"title":"Include Notes"},"description":"Also count the team's internal notes, which are left out unless you ask for them"}],"responses":{"200":{"description":"The file itself","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope `cases:read`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such case or file, or one in a group the key does not see","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"307":{"description":"A signed URL that works for a few minutes; follow it"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cases/{number}/events":{"get":{"tags":["Cases"],"summary":"List a case's events","description":"What happened to the case, oldest first, a page at a time: when it was made, each reply, and every\nchange of status, assignee, priority or type, with who did it. A person is a first name, a key is\nits name.\n\nThe kinds are `created`, `customer_replied`, `team_replied`, `status_changed`, `reopened`, `assigned`,\n`priority_changed` and `type_changed`. Other kinds may be added later; ignore the ones you do not know.\nNothing about the workspace's clocks, the AI's work or the team's notes is part of it.","operationId":"list_case_events_v1_cases__number__events_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"number","in":"path","required":true,"schema":{"type":"integer","description":"The case's number in the workspace","examples":[1042],"title":"Number"},"description":"The case's number in the workspace"},{"name":"after","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The `next_cursor` of the previous page; leave out for the first","examples":["eyJ2Ijog"],"title":"After"},"description":"The `next_cursor` of the previous page; leave out for the first"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"description":"How many to return, at most","default":100,"title":"Limit"},"description":"How many to return, at most"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseEventList"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope `cases:read`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such case or file, or one in a group the key does not see","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The request did not validate","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/groups":{"get":{"tags":["Lookups"],"summary":"List groups","description":"The workspace's groups, by name. A key limited to some groups sees those only. Use an `id` as\n`group_id` when creating a case or searching.","operationId":"list_groups_v1_groups_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupList"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope `cases:read`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/agents":{"get":{"tags":["Lookups"],"summary":"List the team","description":"The people who work in the workspace: an id, a first name and the groups they are in. No surname,\nemail or phone number is shared. Use an `id` as `assignee_id` when searching.\n\nA key limited to some groups sees the people who are in one of them, and only which of the key's groups\nthey are in.","operationId":"list_agents_v1_agents_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentList"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope `cases:read`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/case-types":{"get":{"tags":["Lookups"],"summary":"List case types","description":"The workspace's case types: what `type` takes when you create a case, and what `type` filters on in a\nsearch. Only the ones in use.","operationId":"list_case_types_v1_case_types_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseTypeList"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope `cases:read`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/case-fields":{"get":{"tags":["Lookups"],"summary":"List case fields","description":"The workspace's own fields on a case: the `key` to use in `custom_fields`, what it is called, its\nkind, and for a `select` its choices.","operationId":"list_case_fields_v1_case_fields_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseFieldList"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope `cases:read`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/tags":{"get":{"tags":["Lookups"],"summary":"List tags","description":"The tags on the cases the key sees, with how many cases have each, the most used first. A key limited\nto some groups counts its own cases only.","operationId":"list_tags_v1_tags_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagList"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope `cases:read`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/cases":{"post":{"tags":["Cases"],"summary":"Create a case","description":"Create a case for a person, with what they wrote as its first message.\n\nThe person is found by `email`, then `phone`, then an id in `external_ids`, and made when none is known.\nThe case is routed by the workspace's rules, gets its clocks and is assessed, exactly as a mail would.\nIt arrives on the channel `api`, and its timeline says which key made it.\n\nSend an `Idempotency-Key` so that a retry makes no second case. An `external_ref` finds the case again\n(`GET /v1/cases?external_ref=`); a second create with the same `external_ref` and `source` is 409\n`external_ref_taken` and names the case that has it.","operationId":"create_case_v1_cases_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"A value you make up, such as a UUID, for this one request. Send the same key again, after a timeout or a crash, and you get the first answer back (`Idempotent-Replayed: true`) and nothing is written twice. The same key with another body is 422 `idempotency_key_reused`. Kept for 24 hours","examples":["7c9e6679-7425-40de-944b-e07fc1f90ae7"],"title":"Idempotency-Key"},"description":"A value you make up, such as a UUID, for this one request. Send the same key again, after a timeout or a crash, and you get the first answer back (`Idempotent-Replayed: true`) and nothing is written twice. The same key with another body is 422 `idempotency_key_reused`. Kept for 24 hours"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Case"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope, or the group is not one of the key's","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"The case has changed, is closed, or the `external_ref` is taken","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The request did not validate","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"get":{"tags":["Cases"],"summary":"List or find cases","description":"The cases the key sees, newest first. A case in a group the key does not see is not listed, and not\nfound by its `external_ref` either.\n\nTo find the case you made, send its `external_ref` (and the `source` you made it under, if you gave\none).","operationId":"list_cases_v1_cases_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"external_ref","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Your own id for the case: finds the case you made with it","examples":["order-12345"],"title":"External Ref"},"description":"Your own id for the case: finds the case you made with it"},{"name":"source","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Only cases made under this `source`","examples":["Returns page"],"title":"Source"},"description":"Only cases made under this `source`"},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"enum":["new","open","pending","hold","solved","closed"],"type":"string"}},{"type":"null"}],"description":"Only cases in these statuses","title":"Status"},"description":"Only cases in these statuses"},{"name":"after","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The `next_cursor` of the previous page; leave out for the first","examples":["eyJ2Ijog"],"title":"After"},"description":"The `next_cursor` of the previous page; leave out for the first"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"description":"How many to return, at most","default":50,"title":"Limit"},"description":"How many to return, at most"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseList"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope, or the group is not one of the key's","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The request did not validate","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/cases/{number}":{"get":{"tags":["Cases"],"summary":"Get a case","description":"One case by its number. A case in a group the key does not see is a 404.","operationId":"get_case_v1_cases__number__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"number","in":"path","required":true,"schema":{"type":"integer","description":"The case's number in the workspace","examples":[1042],"title":"Number"},"description":"The case's number in the workspace"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Case"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope, or the group is not one of the key's","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such case, or one in a group the key does not see","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["Cases"],"summary":"Change a case","description":"Change a case's tags, priority, custom fields or `external_ref`. Status and assignment are the team's,\nand sending them is a 422. Send the `version` you read: if the case has moved on the answer is 409\n`case_changed`, and nothing is written.","operationId":"patch_case_v1_cases__number__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"number","in":"path","required":true,"schema":{"type":"integer","description":"The case's number in the workspace","examples":[1042],"title":"Number"},"description":"The case's number in the workspace"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CasePatchIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Case"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope, or the group is not one of the key's","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such case, or one in a group the key does not see","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"The case has changed, is closed, or the `external_ref` is taken","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The request did not validate","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/cases/{number}/messages":{"get":{"tags":["Cases"],"summary":"List a case's messages","description":"The case's public thread, oldest first, a page at a time. The team's internal notes are not part of\nit unless `include_notes` is true; a side conversation never is.","operationId":"list_messages_v1_cases__number__messages_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"number","in":"path","required":true,"schema":{"type":"integer","description":"The case's number in the workspace","examples":[1042],"title":"Number"},"description":"The case's number in the workspace"},{"name":"include_notes","in":"query","required":false,"schema":{"type":"boolean","description":"Also the team's internal notes, which are left out unless you ask","default":false,"title":"Include Notes"},"description":"Also the team's internal notes, which are left out unless you ask"},{"name":"after","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The `next_cursor` of the previous page; leave out for the first","examples":["eyJ2Ijog"],"title":"After"},"description":"The `next_cursor` of the previous page; leave out for the first"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"description":"How many to return, at most","default":100,"title":"Limit"},"description":"How many to return, at most"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageList"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope, or the group is not one of the key's","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such case, or one in a group the key does not see","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The request did not validate","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"tags":["Cases"],"summary":"Add a message to a case","description":"Add to a case. `kind` says what it is:\n\n- `customer`: a message from the person the case is about. It reopens a solved case, as a mail would, and\n  is refused (409 `case_closed`) on a closed one.\n- `note`: internal, for the team, authored by the key. It is never part of the public thread.\n- `reply`: a public answer to the customer, sent through the case's channel as a team reply is (by email\n  for an email case), authored by the key. It needs the scope `cases:reply`; without it the answer is 403\n  and nothing is written. The key does not become the case's assignee. If nothing can carry the answer\n  (no address, no channel) it is 409 `no_way_to_answer` and nothing is written.","operationId":"add_message_v1_cases__number__messages_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"number","in":"path","required":true,"schema":{"type":"integer","description":"The case's number in the workspace","examples":[1042],"title":"Number"},"description":"The case's number in the workspace"},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"A value you make up, such as a UUID, for this one request. Send the same key again, after a timeout or a crash, and you get the first answer back (`Idempotent-Replayed: true`) and nothing is written twice. The same key with another body is 422 `idempotency_key_reused`. Kept for 24 hours","examples":["7c9e6679-7425-40de-944b-e07fc1f90ae7"],"title":"Idempotency-Key"},"description":"A value you make up, such as a UUID, for this one request. Send the same key again, after a timeout or a crash, and you get the first answer back (`Idempotent-Replayed: true`) and nothing is written twice. The same key with another body is 422 `idempotency_key_reused`. Kept for 24 hours"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope, or the group is not one of the key's","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such case, or one in a group the key does not see","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"The case has changed, is closed, or the `external_ref` is taken","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The request did not validate","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/uploads":{"post":{"tags":["Cases"],"summary":"Upload a file","description":"Upload a file as `multipart/form-data` (the part is called `file`), then name its `id` in `attachments`\nof a new case or of a message. The same kinds of file and the same size limit as in the app apply\n(pictures, documents, archives, mail, text; not pages or scripts). A file is yours until a message uses\nit, and only you can use it; one that is never used is deleted after a day.","operationId":"upload_file_v1_uploads_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"A value you make up, such as a UUID, for this one request. Send the same key again, after a timeout or a crash, and you get the first answer back (`Idempotent-Replayed: true`) and nothing is written twice. The same key with another body is 422 `idempotency_key_reused`. Kept for 24 hours","examples":["7c9e6679-7425-40de-944b-e07fc1f90ae7"],"title":"Idempotency-Key"},"description":"A value you make up, such as a UUID, for this one request. Send the same key again, after a timeout or a crash, and you get the first answer back (`Idempotent-Replayed: true`) and nothing is written twice. The same key with another body is 422 `idempotency_key_reused`. Kept for 24 hours"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_file_v1_uploads_post"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Upload"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope, or the group is not one of the key's","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"The file is larger than the limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"415":{"description":"That kind of file cannot be attached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/contacts":{"get":{"tags":["Contacts"],"summary":"List or find contacts","description":"The workspace's contacts, by name, a page at a time. Every filter narrows the list; `email`, `phone`\nand `external_system` with `external_id` are exact matches, so they find the one person you know. A key\nsees every contact, whatever its groups; the counts are of the cases it sees.","operationId":"list_contacts_v1_contacts_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Words to search for in the name, email address, phone number and customer number","title":"Q"},"description":"Words to search for in the name, email address, phone number and customer number"},{"name":"email","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Exactly this email address","examples":["kari@example.no"],"title":"Email"},"description":"Exactly this email address"},{"name":"phone","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Exactly this phone number, compared as digits","examples":["+47 900 00 000"],"title":"Phone"},"description":"Exactly this phone number, compared as digits"},{"name":"external_system","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"With `external_id`: the system whose id you know, as you named it in `external_ids`","examples":["shop"],"title":"External System"},"description":"With `external_id`: the system whose id you know, as you named it in `external_ids`"},{"name":"external_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"With `external_system`: the id in that system","examples":["C-1042"],"title":"External Id"},"description":"With `external_system`: the id in that system"},{"name":"organization_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Only people in this company","title":"Organization Id"},"description":"Only people in this company"},{"name":"after","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The `next_cursor` of the previous page; leave out for the first","examples":["eyJ2Ijog"],"title":"After"},"description":"The `next_cursor` of the previous page; leave out for the first"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"description":"How many to return, at most","default":50,"title":"Limit"},"description":"How many to return, at most"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerList"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The request did not validate","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"tags":["Contacts"],"summary":"Create a contact","description":"Make a contact. A person is never made twice: when the email address, the phone number (as digits) or\nan id in `external_ids` already belongs to a contact, nothing is written and the answer is 409\n`contact_exists` with that contact's id in `details.contact_id`. Look the person up first with\n`GET /v1/contacts`, or just create and read the 409. A person with an address on a company's domain joins\nthat company, as for a mail.\n\nSend an `Idempotency-Key` so that a retry makes nothing twice.","operationId":"create_contact_v1_contacts_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"A value you make up, such as a UUID, for this one request. Send the same key again, after a timeout or a crash, and you get the first answer back (`Idempotent-Replayed: true`) and nothing is written twice. The same key with another body is 422 `idempotency_key_reused`. Kept for 24 hours","examples":["7c9e6679-7425-40de-944b-e07fc1f90ae7"],"title":"Idempotency-Key"},"description":"A value you make up, such as a UUID, for this one request. Send the same key again, after a timeout or a crash, and you get the first answer back (`Idempotent-Replayed: true`) and nothing is written twice. The same key with another body is 422 `idempotency_key_reused`. Kept for 24 hours"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Customer"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such contact or company, or a company named in the body does not exist","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"The email, phone number or external id is held by another, or the name is taken; `details` names the existing one","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The request did not validate","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/contacts/{contact_id}":{"get":{"tags":["Contacts"],"summary":"Get a contact","description":"One contact by id, with the counts of their cases the key sees.","operationId":"get_contact_v1_contacts__contact_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"contact_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","description":"The contact's id","examples":["0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6"],"title":"Contact Id"},"description":"The contact's id"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Customer"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such contact or company, or a company named in the body does not exist","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["Contacts"],"summary":"Change a contact","description":"Change the fields you send; the rest are not touched. `external_ids` is merged key by key (a system's\nid is set, or forgotten with `null`). Giving the contact an email address, phone number or external id\nthat another contact holds is 409 `contact_exists` with that contact's id, and nothing is changed.","operationId":"patch_contact_v1_contacts__contact_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"contact_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","description":"The contact's id","examples":["0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6"],"title":"Contact Id"},"description":"The contact's id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerPatchIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Customer"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such contact or company, or a company named in the body does not exist","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"The email, phone number or external id is held by another, or the name is taken; `details` names the existing one","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The request did not validate","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/contacts/{contact_id}/cases":{"get":{"tags":["Contacts"],"summary":"List a contact's cases","description":"The cases this person is the customer of, newest first, in the same shape as `GET /v1/cases`. It\nneeds the scope `cases:read` besides `contacts:read`, and a case in a group the key does not see is not\nlisted.","operationId":"contact_cases_v1_contacts__contact_id__cases_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"contact_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","description":"The contact's id","examples":["0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6"],"title":"Contact Id"},"description":"The contact's id"},{"name":"after","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The `next_cursor` of the previous page; leave out for the first","examples":["eyJ2Ijog"],"title":"After"},"description":"The `next_cursor` of the previous page; leave out for the first"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"description":"How many to return, at most","default":50,"title":"Limit"},"description":"How many to return, at most"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseList"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such contact or company, or a company named in the body does not exist","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The request did not validate","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/organizations":{"get":{"tags":["Contacts"],"summary":"List or find companies","description":"The workspace's companies, by name, a page at a time. `external_system` with `external_id` finds the\none you know by its id in your own system.","operationId":"list_organizations_v1_organizations_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Words in the company's name","examples":["fliser"],"title":"Q"},"description":"Words in the company's name"},{"name":"external_system","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"With `external_id`: the system whose id you know, as you named it in `external_ids`","examples":["shop"],"title":"External System"},"description":"With `external_id`: the system whose id you know, as you named it in `external_ids`"},{"name":"external_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"With `external_system`: the id in that system","examples":["C-1042"],"title":"External Id"},"description":"With `external_system`: the id in that system"},{"name":"after","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The `next_cursor` of the previous page; leave out for the first","examples":["eyJ2Ijog"],"title":"After"},"description":"The `next_cursor` of the previous page; leave out for the first"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"description":"How many to return, at most","default":50,"title":"Limit"},"description":"How many to return, at most"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrganizationList"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The request did not validate","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"tags":["Contacts"],"summary":"Create a company","description":"Make a company. One with the same name, or the same id in `external_ids`, is not made twice: nothing\nis written and the answer is 409 `organization_exists` with the existing company's id in\n`details.organization_id`. Send an `Idempotency-Key` so that a retry makes nothing twice.","operationId":"create_organization_v1_organizations_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"A value you make up, such as a UUID, for this one request. Send the same key again, after a timeout or a crash, and you get the first answer back (`Idempotent-Replayed: true`) and nothing is written twice. The same key with another body is 422 `idempotency_key_reused`. Kept for 24 hours","examples":["7c9e6679-7425-40de-944b-e07fc1f90ae7"],"title":"Idempotency-Key"},"description":"A value you make up, such as a UUID, for this one request. Send the same key again, after a timeout or a crash, and you get the first answer back (`Idempotent-Replayed: true`) and nothing is written twice. The same key with another body is 422 `idempotency_key_reused`. Kept for 24 hours"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrganizationIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Organization"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"The email, phone number or external id is held by another, or the name is taken; `details` names the existing one","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The request did not validate","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/organizations/{organization_id}":{"get":{"tags":["Contacts"],"summary":"Get a company","description":"One company by id, with how many people belong to it and the counts of its cases the key sees.","operationId":"get_organization_v1_organizations__organization_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"organization_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","description":"The company's id","examples":["0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f9"],"title":"Organization Id"},"description":"The company's id"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Organization"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such contact or company, or a company named in the body does not exist","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["Contacts"],"summary":"Change a company","description":"Change the fields you send; the rest are not touched. `domains` replaces the list; `external_ids` is\nmerged key by key. A name or an external id that another company has is 409 `organization_exists` with\nthat company's id, and nothing is changed.","operationId":"patch_organization_v1_organizations__organization_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"organization_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","description":"The company's id","examples":["0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f9"],"title":"Organization Id"},"description":"The company's id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrganizationPatchIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Organization"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such contact or company, or a company named in the body does not exist","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"The email, phone number or external id is held by another, or the name is taken; `details` names the existing one","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The request did not validate","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/organizations/{organization_id}/contacts":{"get":{"tags":["Contacts"],"summary":"List a company's contacts","description":"The people who belong to the company, by name, a page at a time, in the shape of `GET /v1/contacts`.","operationId":"organization_contacts_v1_organizations__organization_id__contacts_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"organization_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","description":"The company's id","examples":["0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f9"],"title":"Organization Id"},"description":"The company's id"},{"name":"after","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The `next_cursor` of the previous page; leave out for the first","examples":["eyJ2Ijog"],"title":"After"},"description":"The `next_cursor` of the previous page; leave out for the first"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"description":"How many to return, at most","default":50,"title":"Limit"},"description":"How many to return, at most"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerList"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such contact or company, or a company named in the body does not exist","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The request did not validate","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/articles":{"get":{"tags":["Knowledge"],"summary":"List or search articles","description":"The workspace's articles, newest first, a page at a time. `q` is the search the app's Knowledge page\nuses: it matches words, not meaning, and a request never calls a model. An article an import has\nretired is not listed.","operationId":"list_articles_v1_articles_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"description":"Words to look for in the title and text, in Norwegian or English, or letters of the title","examples":["returfrist"],"title":"Q"},"description":"Words to look for in the title and text, in Norwegian or English, or letters of the title"},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"enum":["draft","published"],"type":"string"},{"type":"null"}],"description":"Only drafts, or only published","title":"Status"},"description":"Only drafts, or only published"},{"name":"audience","in":"query","required":false,"schema":{"anyOf":[{"enum":["internal","public"],"type":"string"},{"type":"null"}],"description":"Only `public` or only `internal`","title":"Audience"},"description":"Only `public` or only `internal`"},{"name":"language","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^[a-z]{2,3}$"},{"type":"null"}],"description":"Only this language","examples":["nb"],"title":"Language"},"description":"Only this language"},{"name":"brand_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Only this brand's articles","title":"Brand Id"},"description":"Only this brand's articles"},{"name":"topic","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"description":"A case type's key; `none` is the articles with no topic","examples":["return"],"title":"Topic"},"description":"A case type's key; `none` is the articles with no topic"},{"name":"origin","in":"query","required":false,"schema":{"anyOf":[{"enum":["written","gap","import"],"type":"string"},{"type":"null"}],"description":"Only articles that came in this way","title":"Origin"},"description":"Only articles that came in this way"},{"name":"after","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The `next_cursor` of the previous page; leave out for the first","examples":["0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6"],"title":"After"},"description":"The `next_cursor` of the previous page; leave out for the first"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"description":"How many to return, at most","default":50,"title":"Limit"},"description":"How many to return, at most"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArticleList"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The request did not validate","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"tags":["Knowledge"],"summary":"Create an article","description":"Write an article. It is a draft and internal unless you say otherwise, and it is indexed for search\nas soon as it is saved, exactly as one written in the app is. The key is named in the workspace's\naudit log.\n\nSend an `Idempotency-Key` so that a retry writes one article.","operationId":"create_article_v1_articles_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"A value you make up, such as a UUID, for this one request. Send the same key again, after a timeout or a crash, and you get the first answer back (`Idempotent-Replayed: true`) and nothing is written twice. The same key with another body is 422 `idempotency_key_reused`. Kept for 24 hours","examples":["7c9e6679-7425-40de-944b-e07fc1f90ae7"],"title":"Idempotency-Key"},"description":"A value you make up, such as a UUID, for this one request. Send the same key again, after a timeout or a crash, and you get the first answer back (`Idempotent-Replayed: true`) and nothing is written twice. The same key with another body is 422 `idempotency_key_reused`. Kept for 24 hours"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArticleIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Article"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The request did not validate","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/articles/{article_id}":{"get":{"tags":["Knowledge"],"summary":"Get an article","description":"One article with its text. An id from another workspace, or of an imported page the site no longer has,\nis a 404.","operationId":"get_article_v1_articles__article_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"article_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","description":"The article's id","examples":["0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6"],"title":"Article Id"},"description":"The article's id"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Article"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such article","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["Knowledge"],"summary":"Change an article","description":"Change what you send: title, text, language, brand, audience or topics. A change to the title or\ntext is indexed again. Whether it is published is `publish` and `unpublish`.","operationId":"patch_article_v1_articles__article_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"article_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","description":"The article's id","examples":["0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6"],"title":"Article Id"},"description":"The article's id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArticlePatch"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Article"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such article","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The request did not validate","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/articles/{article_id}/publish":{"post":{"tags":["Knowledge"],"summary":"Publish an article","description":"Make a draft usable: the team can insert it, and the bot can answer from it if its audience is\n`public`. Publishing a published article changes nothing.","operationId":"publish_article_v1_articles__article_id__publish_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"article_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","description":"The article's id","examples":["0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6"],"title":"Article Id"},"description":"The article's id"},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"A value you make up, such as a UUID, for this one request. Send the same key again, after a timeout or a crash, and you get the first answer back (`Idempotent-Replayed: true`) and nothing is written twice. The same key with another body is 422 `idempotency_key_reused`. Kept for 24 hours","examples":["7c9e6679-7425-40de-944b-e07fc1f90ae7"],"title":"Idempotency-Key"},"description":"A value you make up, such as a UUID, for this one request. Send the same key again, after a timeout or a crash, and you get the first answer back (`Idempotent-Replayed: true`) and nothing is written twice. The same key with another body is 422 `idempotency_key_reused`. Kept for 24 hours"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Article"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such article","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/articles/{article_id}/unpublish":{"post":{"tags":["Knowledge"],"summary":"Unpublish an article","description":"Take an article out of use: it becomes a draft again, and neither the team's search nor the bot finds\nit. Nothing is deleted, and publishing it again brings it back.","operationId":"unpublish_article_v1_articles__article_id__unpublish_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"article_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","description":"The article's id","examples":["0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6"],"title":"Article Id"},"description":"The article's id"},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"A value you make up, such as a UUID, for this one request. Send the same key again, after a timeout or a crash, and you get the first answer back (`Idempotent-Replayed: true`) and nothing is written twice. The same key with another body is 422 `idempotency_key_reused`. Kept for 24 hours","examples":["7c9e6679-7425-40de-944b-e07fc1f90ae7"],"title":"Idempotency-Key"},"description":"A value you make up, such as a UUID, for this one request. Send the same key again, after a timeout or a crash, and you get the first answer back (`Idempotent-Replayed: true`) and nothing is written twice. The same key with another body is 422 `idempotency_key_reused`. Kept for 24 hours"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Article"}}}},"401":{"description":"No key, or a key that is wrong, revoked or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The key lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such article","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over the limit; see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"webhooks":{"case.created":{"post":{"tags":["Webhook events"],"summary":"case.created","description":"A case was made.\n\nNolmo sends a `POST` with a JSON body and these headers:\n\n- `webhook-id`: this event's id, the same on every retry and replay. Dedupe by it.\n- `webhook-timestamp`: seconds since the epoch, when this attempt was made.\n- `webhook-signature`: `v1,<base64>` for each valid secret, space separated. The signature is HMAC-SHA256 over `<webhook-id>.<webhook-timestamp>.<body>` with the secret's bytes (the base64 after `whsec_`), as in [Standard Webhooks](https://www.standardwebhooks.com). Refuse a timestamp more than five minutes from your clock and a body whose signature does not match.\n\nAnswer with any `2xx` within ten seconds. Anything else, or no answer, is retried with a growing pause for 24 hours; events of one case arrive in order. An endpoint that answers nothing for three days is turned off and the workspace's admins are told. Redirects are not followed.\n\n```python\nimport base64, hashlib, hmac, time\n\ndef verify(secret: str, headers: dict, body: bytes, tolerance: int = 300) -> bool:\n    \"\"\"True when `body` was signed with `secret` (the whsec_ value) and is fresh.\"\"\"\n    msg_id = headers[\"webhook-id\"]\n    timestamp = headers[\"webhook-timestamp\"]\n    if abs(time.time() - int(timestamp)) > tolerance:\n        return False\n    key = base64.b64decode(secret.removeprefix(\"whsec_\"))\n    signed = f\"{msg_id}.{timestamp}.\".encode() + body\n    expected = base64.b64encode(hmac.new(key, signed, hashlib.sha256).digest()).decode()\n    return any(\n        hmac.compare_digest(expected, part.removeprefix(\"v1,\"))\n        for part in headers[\"webhook-signature\"].split()\n        if part.startswith(\"v1,\")\n    )\n```","operationId":"case_createdcase_created_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseCreatedEvent"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"case.updated":{"post":{"tags":["Webhook events"],"summary":"case.updated","description":"A case's status, assignee, priority or type changed (one event per change).\n\nNolmo sends a `POST` with a JSON body and these headers:\n\n- `webhook-id`: this event's id, the same on every retry and replay. Dedupe by it.\n- `webhook-timestamp`: seconds since the epoch, when this attempt was made.\n- `webhook-signature`: `v1,<base64>` for each valid secret, space separated. The signature is HMAC-SHA256 over `<webhook-id>.<webhook-timestamp>.<body>` with the secret's bytes (the base64 after `whsec_`), as in [Standard Webhooks](https://www.standardwebhooks.com). Refuse a timestamp more than five minutes from your clock and a body whose signature does not match.\n\nAnswer with any `2xx` within ten seconds. Anything else, or no answer, is retried with a growing pause for 24 hours; events of one case arrive in order. An endpoint that answers nothing for three days is turned off and the workspace's admins are told. Redirects are not followed.\n\n```python\nimport base64, hashlib, hmac, time\n\ndef verify(secret: str, headers: dict, body: bytes, tolerance: int = 300) -> bool:\n    \"\"\"True when `body` was signed with `secret` (the whsec_ value) and is fresh.\"\"\"\n    msg_id = headers[\"webhook-id\"]\n    timestamp = headers[\"webhook-timestamp\"]\n    if abs(time.time() - int(timestamp)) > tolerance:\n        return False\n    key = base64.b64decode(secret.removeprefix(\"whsec_\"))\n    signed = f\"{msg_id}.{timestamp}.\".encode() + body\n    expected = base64.b64encode(hmac.new(key, signed, hashlib.sha256).digest()).decode()\n    return any(\n        hmac.compare_digest(expected, part.removeprefix(\"v1,\"))\n        for part in headers[\"webhook-signature\"].split()\n        if part.startswith(\"v1,\")\n    )\n```","operationId":"case_updatedcase_updated_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseUpdatedEvent"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"case.message.created":{"post":{"tags":["Webhook events"],"summary":"case.message.created","description":"A reply the customer sees was added to a case.\n\nNolmo sends a `POST` with a JSON body and these headers:\n\n- `webhook-id`: this event's id, the same on every retry and replay. Dedupe by it.\n- `webhook-timestamp`: seconds since the epoch, when this attempt was made.\n- `webhook-signature`: `v1,<base64>` for each valid secret, space separated. The signature is HMAC-SHA256 over `<webhook-id>.<webhook-timestamp>.<body>` with the secret's bytes (the base64 after `whsec_`), as in [Standard Webhooks](https://www.standardwebhooks.com). Refuse a timestamp more than five minutes from your clock and a body whose signature does not match.\n\nAnswer with any `2xx` within ten seconds. Anything else, or no answer, is retried with a growing pause for 24 hours; events of one case arrive in order. An endpoint that answers nothing for three days is turned off and the workspace's admins are told. Redirects are not followed.\n\n```python\nimport base64, hashlib, hmac, time\n\ndef verify(secret: str, headers: dict, body: bytes, tolerance: int = 300) -> bool:\n    \"\"\"True when `body` was signed with `secret` (the whsec_ value) and is fresh.\"\"\"\n    msg_id = headers[\"webhook-id\"]\n    timestamp = headers[\"webhook-timestamp\"]\n    if abs(time.time() - int(timestamp)) > tolerance:\n        return False\n    key = base64.b64decode(secret.removeprefix(\"whsec_\"))\n    signed = f\"{msg_id}.{timestamp}.\".encode() + body\n    expected = base64.b64encode(hmac.new(key, signed, hashlib.sha256).digest()).decode()\n    return any(\n        hmac.compare_digest(expected, part.removeprefix(\"v1,\"))\n        for part in headers[\"webhook-signature\"].split()\n        if part.startswith(\"v1,\")\n    )\n```","operationId":"case_message_createdcase_message_created_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseMessageCreatedEvent"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"case.note.created":{"post":{"tags":["Webhook events"],"summary":"case.note.created","description":"An internal note was added to a case. Only sent to an endpoint that asks for it.\n\nNolmo sends a `POST` with a JSON body and these headers:\n\n- `webhook-id`: this event's id, the same on every retry and replay. Dedupe by it.\n- `webhook-timestamp`: seconds since the epoch, when this attempt was made.\n- `webhook-signature`: `v1,<base64>` for each valid secret, space separated. The signature is HMAC-SHA256 over `<webhook-id>.<webhook-timestamp>.<body>` with the secret's bytes (the base64 after `whsec_`), as in [Standard Webhooks](https://www.standardwebhooks.com). Refuse a timestamp more than five minutes from your clock and a body whose signature does not match.\n\nAnswer with any `2xx` within ten seconds. Anything else, or no answer, is retried with a growing pause for 24 hours; events of one case arrive in order. An endpoint that answers nothing for three days is turned off and the workspace's admins are told. Redirects are not followed.\n\n```python\nimport base64, hashlib, hmac, time\n\ndef verify(secret: str, headers: dict, body: bytes, tolerance: int = 300) -> bool:\n    \"\"\"True when `body` was signed with `secret` (the whsec_ value) and is fresh.\"\"\"\n    msg_id = headers[\"webhook-id\"]\n    timestamp = headers[\"webhook-timestamp\"]\n    if abs(time.time() - int(timestamp)) > tolerance:\n        return False\n    key = base64.b64decode(secret.removeprefix(\"whsec_\"))\n    signed = f\"{msg_id}.{timestamp}.\".encode() + body\n    expected = base64.b64encode(hmac.new(key, signed, hashlib.sha256).digest()).decode()\n    return any(\n        hmac.compare_digest(expected, part.removeprefix(\"v1,\"))\n        for part in headers[\"webhook-signature\"].split()\n        if part.startswith(\"v1,\")\n    )\n```","operationId":"case_note_createdcase_note_created_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseNoteCreatedEvent"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"Agent":{"properties":{"id":{"type":"string","format":"uuid","title":"Id","description":"Use it as `assignee_id` when searching"},"first_name":{"type":"string","title":"First Name","description":"The first name only: no surname, email or phone number is shared"},"group_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Group Ids","description":"The groups the person is in. A key limited to some groups sees those of them only"}},"type":"object","required":["id","first_name","group_ids"],"title":"Agent","examples":[{"first_name":"Astrid","group_ids":["0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6"],"id":"0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6"}]},"AgentList":{"properties":{"items":{"items":{"$ref":"#/components/schemas/Agent"},"type":"array","title":"Items"}},"type":"object","required":["items"],"title":"AgentList","examples":[{"items":[{"first_name":"Astrid","group_ids":["0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6"],"id":"0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6"}]}]},"Article":{"properties":{"id":{"type":"string","format":"uuid","title":"Id","description":"The article's id","examples":["0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6"]},"title":{"type":"string","title":"Title","description":"The title","examples":["Returfrist for fliser"]},"excerpt":{"type":"string","title":"Excerpt","description":"The body's first 200 characters"},"language":{"type":"string","title":"Language","description":"The language of the text, such as `nb` or `en`","examples":["nb"]},"status":{"type":"string","enum":["draft","published"],"title":"Status","description":"`draft` is the team's alone; `published` can be used"},"audience":{"type":"string","enum":["internal","public"],"title":"Audience","description":"`public` articles may be used to answer customers; `internal` ones are for the team"},"origin":{"type":"string","enum":["written","gap","import"],"title":"Origin","description":"`written` by a person or a key, `gap` from a knowledge gap, `import` from a help centre"},"topics":{"items":{"type":"string"},"type":"array","title":"Topics","description":"The case types (by key) the article serves; empty is no topic"},"brand_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Brand Id","description":"The brand it belongs to; null is every brand"},"source_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Url","description":"An imported page's address, else null"},"published_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Published At","description":"When it was first published; null for a draft"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"body":{"type":"string","title":"Body","description":"The text, as it is stored: Markdown or plain text","examples":["Returfristen er 30 dager. Send varene uåpnet i retur sammen med kvitteringen."]}},"type":"object","required":["id","title","excerpt","language","status","audience","origin","topics","brand_id","source_url","published_at","created_at","updated_at","body"],"title":"Article","description":"One article, with its text.","examples":[{"audience":"public","body":"Returfristen er 30 dager. Send varene uåpnet i retur sammen med kvitteringen.","created_at":"2026-10-20T08:00:00Z","excerpt":"Returfristen er 30 dager. Send varene uåpnet i retur sammen med kvitteringen.","id":"0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6","language":"nb","origin":"written","published_at":"2026-10-20T08:15:00Z","status":"published","title":"Returfrist for fliser","topics":["return"],"updated_at":"2026-10-20T08:15:00Z"}]},"ArticleIn":{"properties":{"title":{"type":"string","maxLength":300,"minLength":1,"title":"Title","description":"The title","examples":["Returfrist for fliser"]},"body":{"type":"string","maxLength":100000,"minLength":1,"title":"Body","description":"The text, Markdown or plain. If it holds HTML tags, scripts, styles and anything else a page may not carry are removed before it is stored","examples":["Returfristen er 30 dager. Send varene uåpnet i retur sammen med kvitteringen."]},"language":{"anyOf":[{"type":"string","pattern":"^[a-z]{2,3}$"},{"type":"null"}],"title":"Language","description":"The language of the text. Left out, the workspace's default language","examples":["nb"]},"brand_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Brand Id","description":"A brand of the workspace; null is every brand"},"audience":{"type":"string","enum":["internal","public"],"title":"Audience","description":"`public` lets the bot use it once published","default":"internal"},"status":{"type":"string","enum":["draft","published"],"title":"Status","description":"`published` makes it usable at once","default":"draft"},"topics":{"items":{"type":"string"},"type":"array","maxItems":20,"title":"Topics","description":"Case types, by key, the article serves"}},"type":"object","required":["title","body"],"title":"ArticleIn","description":"A new article. It is a draft until you publish it, and an internal one until you say `public`.","examples":[{"audience":"public","body":"Returfristen er 30 dager. Send varene uåpnet i retur sammen med kvitteringen.","language":"nb","status":"published","title":"Returfrist for fliser","topics":["return"]}]},"ArticleList":{"properties":{"items":{"items":{"$ref":"#/components/schemas/ArticleSummary"},"type":"array","title":"Items"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor","description":"Send as `after` for the next page; null on the last","examples":["0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6"]}},"type":"object","required":["items"],"title":"ArticleList","description":"A page of articles, newest first.","examples":[{"items":[{"audience":"public","created_at":"2026-10-20T08:00:00Z","excerpt":"Returfristen er 30 dager. Send varene uåpnet i retur sammen med kvitteringen.","id":"0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6","language":"nb","origin":"written","published_at":"2026-10-20T08:15:00Z","status":"published","title":"Returfrist for fliser","topics":["return"],"updated_at":"2026-10-20T08:15:00Z"}]}]},"ArticlePatch":{"properties":{"title":{"anyOf":[{"type":"string","maxLength":300,"minLength":1},{"type":"null"}],"title":"Title","description":"A new title"},"body":{"anyOf":[{"type":"string","maxLength":100000,"minLength":1},{"type":"null"}],"title":"Body","description":"A new text; HTML is cleaned as on create"},"language":{"anyOf":[{"type":"string","pattern":"^[a-z]{2,3}$"},{"type":"null"}],"title":"Language","description":"A new language"},"brand_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Brand Id","description":"A brand of the workspace, or null for every brand"},"audience":{"anyOf":[{"type":"string","enum":["internal","public"]},{"type":"null"}],"title":"Audience","description":"`public` or `internal`"},"topics":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":20},{"type":"null"}],"title":"Topics","description":"Replaces the case types the article serves"}},"type":"object","title":"ArticlePatch","description":"Only what is sent changes. `brand_id: null` clears the brand; `topics` replaces the list whole.\nPublishing and unpublishing have their own routes.","examples":[{"audience":"public","body":"Returfristen er 60 dager."}]},"ArticleSummary":{"properties":{"id":{"type":"string","format":"uuid","title":"Id","description":"The article's id","examples":["0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6"]},"title":{"type":"string","title":"Title","description":"The title","examples":["Returfrist for fliser"]},"excerpt":{"type":"string","title":"Excerpt","description":"The body's first 200 characters"},"language":{"type":"string","title":"Language","description":"The language of the text, such as `nb` or `en`","examples":["nb"]},"status":{"type":"string","enum":["draft","published"],"title":"Status","description":"`draft` is the team's alone; `published` can be used"},"audience":{"type":"string","enum":["internal","public"],"title":"Audience","description":"`public` articles may be used to answer customers; `internal` ones are for the team"},"origin":{"type":"string","enum":["written","gap","import"],"title":"Origin","description":"`written` by a person or a key, `gap` from a knowledge gap, `import` from a help centre"},"topics":{"items":{"type":"string"},"type":"array","title":"Topics","description":"The case types (by key) the article serves; empty is no topic"},"brand_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Brand Id","description":"The brand it belongs to; null is every brand"},"source_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Url","description":"An imported page's address, else null"},"published_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Published At","description":"When it was first published; null for a draft"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","title","excerpt","language","status","audience","origin","topics","brand_id","source_url","published_at","created_at","updated_at"],"title":"ArticleSummary","description":"An article without its body, as the list shows it."},"Attachment":{"properties":{"id":{"type":"string","title":"Id","description":"Use it in `attachments` of a message"},"name":{"type":"string","title":"Name"},"content_type":{"type":"string","title":"Content Type"},"size":{"type":"integer","title":"Size","description":"Bytes"}},"type":"object","required":["id","name","content_type","size"],"title":"Attachment"},"Author":{"properties":{"type":{"type":"string","enum":["customer","team","api","ai"],"title":"Type","description":"`customer`: the person the case is about. `team`: someone in the workspace, by first name. `api`: a key, by its name. `ai`: the workspace's AI"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"}},"type":"object","required":["type","name"],"title":"Author"},"Body_upload_file_v1_uploads_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"}},"type":"object","required":["file"],"title":"Body_upload_file_v1_uploads_post"},"Case":{"properties":{"number":{"type":"integer","title":"Number","description":"The case's number in the workspace; the id in the paths","examples":[1042]},"subject":{"type":"string","title":"Subject"},"status":{"type":"string","enum":["new","open","pending","hold","solved","closed"],"title":"Status","description":"`new`, `open`, `pending`, `hold`, `solved` or `closed`"},"priority":{"type":"string","enum":["low","normal","high","urgent"],"title":"Priority"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Type","description":"The case type's key"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"custom_fields":{"additionalProperties":true,"type":"object","title":"Custom Fields"},"external_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"External Ref","description":"Your own id for the case, if it has one"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source","description":"The `source` the external_ref belongs to"},"channel":{"type":"string","title":"Channel","description":"How the case arrived: `api` for one made here","examples":["api"]},"group_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Group Id"},"brand_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Brand Id"},"assignee_first_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Assignee First Name","description":"The first name of the person who has the case"},"contact":{"$ref":"#/components/schemas/Contact"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"solved_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Solved At"},"last_message_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Message At"},"version":{"type":"integer","title":"Version","description":"Send it back in `version` of a PATCH"}},"type":"object","required":["number","subject","status","priority","type","tags","custom_fields","external_ref","source","channel","group_id","brand_id","assignee_first_name","contact","created_at","updated_at","solved_at","last_message_at","version"],"title":"Case","description":"A case, as far as a key may see it.","examples":[{"channel":"api","contact":{"email":"kari@example.no","id":"0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6","language":"nb","name":"Kari Kunde"},"created_at":"2026-11-09T09:00:00Z","custom_fields":{},"external_ref":"order-12345","group_id":"0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6","last_message_at":"2026-11-09T09:00:00Z","number":1042,"priority":"normal","source":"Returns page","status":"new","subject":"Cracked tiles in the delivery","tags":["delivery"],"updated_at":"2026-11-09T09:00:00Z","version":1}]},"CaseCounts":{"properties":{"cases":{"type":"integer","title":"Cases","description":"Cases, spam left out"},"open":{"type":"integer","title":"Open","description":"Of those, the ones still with the team: new, open, pending or on hold"},"last_contact_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Contact At","description":"When they last wrote or were written to"}},"type":"object","required":["cases","open","last_contact_at"],"title":"CaseCounts","description":"How many cases a person or a company has, counting only the cases the key may see."},"CaseCreatedEvent":{"properties":{"id":{"type":"string","format":"uuid","title":"Id","description":"This event for this endpoint, the same on every retry and every replay: the receiver's key to dedupe by"},"created_at":{"type":"string","format":"date-time","title":"Created At","description":"When it happened, not when it was sent"},"type":{"type":"string","const":"case.created","title":"Type","default":"case.created"},"data":{"$ref":"#/components/schemas/CaseData"}},"type":"object","required":["id","created_at","data"],"title":"CaseCreatedEvent","description":"A case was made, by a person, a customer's message or another system.","examples":[{"created_at":"2026-11-10T08:15:00Z","data":{"case":{"assignee":"Astrid","channel":"email","contact":{"email":"kari@example.com","id":"7c2e4a1b-9d3f-4f6a-8b5e-1a2b3c4d5e6f","name":"Kari Kunde"},"created_at":"2026-11-10T08:15:00Z","id":"5d0b8f0e-2a4c-7d3e-9c1a-3b6f2e8a1c42","number":1042,"priority":"high","status":"open","subject":"Cracked tile in the delivery","tags":["delivery","tiles"],"type":"complaint","updated_at":"2026-11-10T08:20:41Z"}},"id":"0192f3a4-3333-7e2d-a3f4-5b6c7d8e9f01","type":"case.created"}]},"CaseData":{"properties":{"case":{"$ref":"#/components/schemas/PublicCase"}},"type":"object","required":["case"],"title":"CaseData"},"CaseEvent":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"kind":{"type":"string","enum":["created","customer_replied","team_replied","status_changed","reopened","assigned","priority_changed","type_changed"],"title":"Kind","description":"`created`; `customer_replied` and `team_replied` (`message_id` says which message); `status_changed`, `reopened`, `priority_changed` and `type_changed` (`from` and `to`); `assigned` (`from` and `to` are first names, null for nobody). More kinds may be added: ignore the ones you do not know"},"actor":{"$ref":"#/components/schemas/EventActor"},"from":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"From","description":"The value before, where there is one"},"to":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To","description":"The value after, where there is one"},"message_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Message Id","description":"The message, for a reply"},"at":{"type":"string","format":"date-time","title":"At"}},"type":"object","required":["id","kind","actor","at"],"title":"CaseEvent","examples":[{"actor":{"name":"Astrid","type":"team"},"at":"2026-11-09T11:02:00Z","from":"open","id":"0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6","kind":"status_changed","to":"solved"}]},"CaseEventList":{"properties":{"items":{"items":{"$ref":"#/components/schemas/CaseEvent"},"type":"array","title":"Items"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor","description":"Send it as `after` for the next page; null on the last"}},"type":"object","required":["items","next_cursor"],"title":"CaseEventList","examples":[{"items":[{"actor":{"name":"Astrid","type":"team"},"at":"2026-11-09T11:02:00Z","from":"open","id":"0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6","kind":"status_changed","to":"solved"}]}]},"CaseField":{"properties":{"key":{"type":"string","title":"Key","description":"The key in a case's `custom_fields`"},"label":{"type":"string","title":"Label"},"kind":{"type":"string","enum":["text","number","select","date","checkbox"],"title":"Kind","description":"`text`, `number`, `select`, `date` or `checkbox`"},"options":{"items":{"$ref":"#/components/schemas/FieldOption"},"type":"array","title":"Options","description":"The choices of a `select`; empty for the other kinds"}},"type":"object","required":["key","label","kind","options"],"title":"CaseField","examples":[{"key":"order_no","kind":"text","label":"Order number","options":[]},{"key":"carrier","kind":"select","label":"Carrier","options":[{"label":"Posten","value":"posten"},{"label":"DHL","value":"dhl"}]}]},"CaseFieldList":{"properties":{"items":{"items":{"$ref":"#/components/schemas/CaseField"},"type":"array","title":"Items"}},"type":"object","required":["items"],"title":"CaseFieldList","examples":[{"items":[{"key":"order_no","kind":"text","label":"Order number","options":[]},{"key":"carrier","kind":"select","label":"Carrier","options":[{"label":"Posten","value":"posten"},{"label":"DHL","value":"dhl"}]}]}]},"CaseFile":{"properties":{"id":{"type":"string","title":"Id","description":"Download it with `GET /v1/attachments/{id}`"},"name":{"type":"string","title":"Name"},"content_type":{"type":"string","title":"Content Type"},"size":{"type":"integer","title":"Size","description":"Bytes"},"message_id":{"type":"string","format":"uuid","title":"Message Id","description":"The message it hangs on"},"on":{"type":"string","enum":["message","note"],"title":"On","description":"`message`: on a public message. `note`: on an internal note, listed only when asked for"},"created_at":{"type":"string","format":"date-time","title":"Created At","description":"When the message was written"}},"type":"object","required":["id","name","content_type","size","message_id","on","created_at"],"title":"CaseFile","examples":[{"content_type":"image/jpeg","created_at":"2026-11-09T10:30:00Z","id":"0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6","message_id":"0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6","name":"damaged-tiles.jpg","on":"message","size":183204}]},"CaseFileList":{"properties":{"items":{"items":{"$ref":"#/components/schemas/CaseFile"},"type":"array","title":"Items"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor","description":"Send it as `after` for the next page; null on the last"}},"type":"object","required":["items","next_cursor"],"title":"CaseFileList","examples":[{"items":[{"content_type":"image/jpeg","created_at":"2026-11-09T10:30:00Z","id":"0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6","message_id":"0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6","name":"damaged-tiles.jpg","on":"message","size":183204}]}]},"CaseIn":{"properties":{"contact":{"$ref":"#/components/schemas/ContactIn"},"subject":{"type":"string","maxLength":500,"minLength":1,"title":"Subject","description":"The case's title"},"message":{"$ref":"#/components/schemas/FirstMessageIn"},"priority":{"type":"string","enum":["low","normal","high","urgent"],"title":"Priority","description":"`low`, `normal`, `high` or `urgent`","default":"normal"},"type":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Type","description":"One of the workspace's case types, by its key"},"tags":{"items":{"type":"string"},"type":"array","maxItems":20,"title":"Tags","description":"Labels to put on the case"},"brand_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Brand Id","description":"The brand or store the case belongs to"},"group_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Group Id","description":"The group the case goes to. It must be one of the key's groups (`GET /v1/me`); left out, the workspace's rules choose"},"custom_fields":{"additionalProperties":true,"type":"object","title":"Custom Fields","description":"Values for the workspace's case fields, by the field's key"},"external_ref":{"anyOf":[{"type":"string","maxLength":200,"minLength":1},{"type":"null"}],"title":"External Ref","description":"Your own id for the case. A second create with the same id from the same `source` is refused with 409 `external_ref_taken` and the number of the case that has it","examples":["order-1042"]},"source":{"anyOf":[{"type":"string","maxLength":60,"minLength":1},{"type":"null"}],"title":"Source","description":"What you call your system, such as `Contact form`. `external_ref` is unique within it. Left out, it is the key's name","examples":["Contact form"]}},"type":"object","required":["contact","subject","message"],"title":"CaseIn","description":"A new case: a person, a subject and what they wrote. It is routed by the workspace's triggers, gets its\nclocks and is assessed, exactly as a mail would.","examples":[{"contact":{"email":"kari@example.no","name":"Kari Kunde"},"external_ref":"order-12345","message":{"body_text":"Three of the tiles in the pack were cracked. Order 12345."},"priority":"normal","source":"Returns page","subject":"Cracked tiles in the delivery","tags":["delivery"]}]},"CaseList":{"properties":{"items":{"items":{"$ref":"#/components/schemas/Case"},"type":"array","title":"Items"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor","description":"Send it as `after` for the next page; null on the last"}},"type":"object","required":["items","next_cursor"],"title":"CaseList","examples":[{"items":[{"channel":"api","contact":{"email":"kari@example.no","id":"0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6","language":"nb","name":"Kari Kunde"},"created_at":"2026-11-09T09:00:00Z","custom_fields":{},"external_ref":"order-12345","group_id":"0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6","last_message_at":"2026-11-09T09:00:00Z","number":1042,"priority":"normal","source":"Returns page","status":"new","subject":"Cracked tiles in the delivery","tags":["delivery"],"updated_at":"2026-11-09T09:00:00Z","version":1}]}]},"CaseMessageCreatedEvent":{"properties":{"id":{"type":"string","format":"uuid","title":"Id","description":"This event for this endpoint, the same on every retry and every replay: the receiver's key to dedupe by"},"created_at":{"type":"string","format":"date-time","title":"Created At","description":"When it happened, not when it was sent"},"type":{"type":"string","const":"case.message.created","title":"Type","default":"case.message.created"},"data":{"$ref":"#/components/schemas/MessageData"}},"type":"object","required":["id","created_at","data"],"title":"CaseMessageCreatedEvent","description":"A reply the customer sees was added to a case: theirs, the team's or the AI's. Internal notes are\n`case.note.created`.","examples":[{"created_at":"2026-11-10T08:20:41Z","data":{"case":{"assignee":"Astrid","channel":"email","contact":{"email":"kari@example.com","id":"7c2e4a1b-9d3f-4f6a-8b5e-1a2b3c4d5e6f","name":"Kari Kunde"},"created_at":"2026-11-10T08:15:00Z","id":"5d0b8f0e-2a4c-7d3e-9c1a-3b6f2e8a1c42","number":1042,"priority":"high","status":"open","subject":"Cracked tile in the delivery","tags":["delivery","tiles"],"type":"complaint","updated_at":"2026-11-10T08:20:41Z"},"message":{"author_kind":"customer","created_at":"2026-11-10T08:20:41Z","id":"0192f3a4-7b1c-7e2d-a3f4-5b6c7d8e9f01","kind":"public","text":"Hi, three of the tiles in the pallet were cracked."}},"id":"0192f3a4-5555-7e2d-a3f4-5b6c7d8e9f01","type":"case.message.created"}]},"CaseNoteCreatedEvent":{"properties":{"id":{"type":"string","format":"uuid","title":"Id","description":"This event for this endpoint, the same on every retry and every replay: the receiver's key to dedupe by"},"created_at":{"type":"string","format":"date-time","title":"Created At","description":"When it happened, not when it was sent"},"type":{"type":"string","const":"case.note.created","title":"Type","default":"case.note.created"},"data":{"$ref":"#/components/schemas/MessageData"}},"type":"object","required":["id","created_at","data"],"title":"CaseNoteCreatedEvent","description":"An internal note was added to a case. Opt-in: an endpoint hears it only when it asks for it.","examples":[{"created_at":"2026-11-10T08:22:00Z","data":{"case":{"assignee":"Astrid","channel":"email","contact":{"email":"kari@example.com","id":"7c2e4a1b-9d3f-4f6a-8b5e-1a2b3c4d5e6f","name":"Kari Kunde"},"created_at":"2026-11-10T08:15:00Z","id":"5d0b8f0e-2a4c-7d3e-9c1a-3b6f2e8a1c42","number":1042,"priority":"high","status":"open","subject":"Cracked tile in the delivery","tags":["delivery","tiles"],"type":"complaint","updated_at":"2026-11-10T08:20:41Z"},"message":{"author_kind":"team","created_at":"2026-11-10T08:20:41Z","id":"0192f3a4-7b1c-7e2d-a3f4-5b6c7d8e9f01","kind":"internal","text":"Replacement tiles ordered."}},"id":"0192f3a4-6666-7e2d-a3f4-5b6c7d8e9f01","type":"case.note.created"}]},"CasePatchIn":{"properties":{"tags":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":20},{"type":"null"}],"title":"Tags","description":"Replaces the case's tags"},"priority":{"anyOf":[{"type":"string","enum":["low","normal","high","urgent"]},{"type":"null"}],"title":"Priority","description":"`low`, `normal`, `high` or `urgent`"},"custom_fields":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Custom Fields","description":"Values for the case fields, merged key by key"},"external_ref":{"anyOf":[{"type":"string","maxLength":200,"minLength":1},{"type":"null"}],"title":"External Ref","description":"Your own id for the case; `null` takes it away"},"version":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Version","description":"The `version` you read. When the case has moved on the answer is 409 `case_changed`"}},"additionalProperties":false,"type":"object","title":"CasePatchIn","description":"What a caller may change on a case. Status and assignment stay the team's: sending them is a 422.","examples":[{"priority":"high","tags":["delivery","refund"],"version":3}]},"CaseType":{"properties":{"key":{"type":"string","title":"Key","description":"What `type` takes on a case, and what `type` filters on"},"name":{"type":"string","title":"Name"}},"type":"object","required":["key","name"],"title":"CaseType","examples":[{"key":"return","name":"Return"}]},"CaseTypeList":{"properties":{"items":{"items":{"$ref":"#/components/schemas/CaseType"},"type":"array","title":"Items"}},"type":"object","required":["items"],"title":"CaseTypeList","examples":[{"items":[{"key":"return","name":"Return"}]}]},"CaseUpdatedData":{"properties":{"case":{"$ref":"#/components/schemas/PublicCase"},"changes":{"items":{"$ref":"#/components/schemas/Change"},"type":"array","title":"Changes","description":"What this event is about; one event per change"}},"type":"object","required":["case","changes"],"title":"CaseUpdatedData"},"CaseUpdatedEvent":{"properties":{"id":{"type":"string","format":"uuid","title":"Id","description":"This event for this endpoint, the same on every retry and every replay: the receiver's key to dedupe by"},"created_at":{"type":"string","format":"date-time","title":"Created At","description":"When it happened, not when it was sent"},"type":{"type":"string","const":"case.updated","title":"Type","default":"case.updated"},"data":{"$ref":"#/components/schemas/CaseUpdatedData"}},"type":"object","required":["id","created_at","data"],"title":"CaseUpdatedEvent","description":"A case's status, assignee, priority or type changed. `data.case` is the case as it is when the event\nis sent; `data.changes` says what this event is about.","examples":[{"created_at":"2026-11-10T08:18:00Z","data":{"case":{"assignee":"Astrid","channel":"email","contact":{"email":"kari@example.com","id":"7c2e4a1b-9d3f-4f6a-8b5e-1a2b3c4d5e6f","name":"Kari Kunde"},"created_at":"2026-11-10T08:15:00Z","id":"5d0b8f0e-2a4c-7d3e-9c1a-3b6f2e8a1c42","number":1042,"priority":"high","status":"open","subject":"Cracked tile in the delivery","tags":["delivery","tiles"],"type":"complaint","updated_at":"2026-11-10T08:20:41Z"},"changes":[{"field":"assignee","to":"Astrid"}]},"id":"0192f3a4-4444-7e2d-a3f4-5b6c7d8e9f01","type":"case.updated"}]},"Change":{"properties":{"field":{"type":"string","enum":["status","assignee","priority","type"],"title":"Field"},"from":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"From"},"to":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To"}},"type":"object","required":["field","from","to"],"title":"Change","description":"One thing that changed on a case. `from` and `to` are the status, the priority or the type's key,\nor the first name of the assignee."},"Contact":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"language":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Language","description":"`nb` or `en`, when known"}},"type":"object","required":["id","name","email","phone","language"],"title":"Contact"},"ContactIn":{"properties":{"name":{"type":"string","maxLength":200,"minLength":1,"title":"Name","description":"Their name, used when they are new"},"email":{"anyOf":[{"type":"string","format":"email"},{"type":"null"}],"title":"Email","description":"Their email address"},"phone":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Phone","description":"Their phone number"},"language":{"anyOf":[{"type":"string","maxLength":5},{"type":"null"}],"title":"Language","description":"Their language, `nb` or `en`, used when they are new"},"external_ids":{"additionalProperties":{"type":"string"},"type":"object","maxProperties":10,"title":"External Ids","description":"Their id in your own systems, by the system's name: `{\"shop\": \"C-1042\"}`"}},"type":"object","required":["name"],"title":"ContactIn","description":"The person the case is about, found or made. Give at least one of `email`, `phone` and `external_ids`:\nthe person is found by the email, then the phone number, then an id in another system (exact matches\nonly), and made when none is known. A person who is found is not changed.","examples":[{"email":"kari@example.no","language":"nb","name":"Kari Kunde","phone":"+47 900 00 000"}]},"Customer":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email","description":"Lowercased. Unique in the workspace"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone","description":"Digits with a leading `+`"},"language":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Language","description":"`nb` or `en`, when known"},"customer_no":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer No","description":"Their customer number"},"member_no":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Member No","description":"Their member number"},"external_ids":{"additionalProperties":{"type":"string"},"type":"object","title":"External Ids","description":"Their ids in your own systems, by the system's name: `{\"shop\": \"C-1042\"}`"},"organization_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Organization Id","description":"The company they belong to"},"organization_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Organization Name"},"case_counts":{"$ref":"#/components/schemas/CaseCounts"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","email","phone","language","customer_no","member_no","external_ids","organization_id","organization_name","case_counts","created_at","updated_at"],"title":"Customer","description":"A customer: a person who writes to the workspace.","examples":[{"case_counts":{"cases":3,"last_contact_at":"2026-10-20T08:15:00Z","open":1},"created_at":"2026-09-02T10:00:00Z","customer_no":"10442","email":"kari@example.no","external_ids":{"shop":"C-1042"},"id":"0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6","language":"nb","name":"Kari Kunde","organization_id":"0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f9","organization_name":"Fliser AS","phone":"+4790000000","updated_at":"2026-10-20T08:15:00Z"}]},"CustomerIn":{"properties":{"name":{"type":"string","maxLength":200,"minLength":1,"title":"Name","description":"Their name"},"email":{"anyOf":[{"type":"string","format":"email"},{"type":"null"}],"title":"Email","description":"Their email address"},"phone":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Phone","description":"Their phone number"},"language":{"anyOf":[{"type":"string","maxLength":5},{"type":"null"}],"title":"Language","description":"`nb` or `en`"},"customer_no":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Customer No"},"member_no":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Member No"},"organization_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Organization Id","description":"The company they belong to. Left out, a company with their email's domain is used"},"external_ids":{"additionalProperties":{"type":"string"},"type":"object","maxProperties":10,"title":"External Ids","description":"Their ids in your own systems, by the system's name: `{\"shop\": \"C-1042\"}`"}},"additionalProperties":false,"type":"object","required":["name"],"title":"CustomerIn","description":"A new contact. A person whose email, phone number or id in another system is already known is not made\ntwice: the answer is 409 `contact_exists` with the existing contact's id in `details.contact_id`.","examples":[{"email":"kari@example.no","external_ids":{"shop":"C-1042"},"language":"nb","name":"Kari Kunde","phone":"+47 900 00 000"}]},"CustomerList":{"properties":{"items":{"items":{"$ref":"#/components/schemas/Customer"},"type":"array","title":"Items"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor","description":"Send it as `after` for the next page; null on the last"}},"type":"object","required":["items","next_cursor"],"title":"CustomerList","examples":[{"items":[{"case_counts":{"cases":3,"last_contact_at":"2026-10-20T08:15:00Z","open":1},"created_at":"2026-09-02T10:00:00Z","customer_no":"10442","email":"kari@example.no","external_ids":{"shop":"C-1042"},"id":"0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6","language":"nb","name":"Kari Kunde","organization_id":"0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f9","organization_name":"Fliser AS","phone":"+4790000000","updated_at":"2026-10-20T08:15:00Z"}]}]},"CustomerPatchIn":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":200,"minLength":1},{"type":"null"}],"title":"Name","description":"Never null"},"email":{"anyOf":[{"type":"string","format":"email"},{"type":"null"}],"title":"Email","description":"Another email address; `null` takes it away"},"phone":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Phone"},"language":{"anyOf":[{"type":"string","maxLength":5},{"type":"null"}],"title":"Language"},"customer_no":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Customer No"},"member_no":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Member No"},"organization_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Organization Id","description":"`null` takes them out of their company"},"external_ids":{"additionalProperties":{"anyOf":[{"type":"string"},{"type":"null"}]},"type":"object","maxProperties":10,"title":"External Ids","description":"Merged key by key: a system's id is set, or forgotten with `null`. Systems you leave out are kept"}},"additionalProperties":false,"type":"object","title":"CustomerPatchIn","description":"What to change on a contact. Fields left out are not touched; `null` empties an optional field.","examples":[{"external_ids":{"shop":"C-2000"},"organization_id":"0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f9","phone":"+47 911 22 333"}]},"ErrorBody":{"properties":{"code":{"type":"string","title":"Code"},"message":{"type":"string","title":"Message"},"details":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Details"}},"type":"object","required":["code","message"],"title":"ErrorBody"},"ErrorResponse":{"properties":{"error":{"$ref":"#/components/schemas/ErrorBody"}},"type":"object","required":["error"],"title":"ErrorResponse","description":"Declare on operations that can fail: `responses={404: {\"model\": ErrorResponse}}`."},"EventActor":{"properties":{"type":{"type":"string","enum":["customer","team","api","ai","automation","system"],"title":"Type","description":"`customer`: the person the case is about. `team`: someone in the workspace, by first name. `api`: a key, by its name. `ai`, `automation` and `system` are Nolmo itself"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"}},"type":"object","required":["type","name"],"title":"EventActor"},"FieldOption":{"properties":{"value":{"type":"string","title":"Value"},"label":{"type":"string","title":"Label"}},"type":"object","required":["value","label"],"title":"FieldOption"},"FirstMessageIn":{"properties":{"body_text":{"type":"string","maxLength":100000,"minLength":1,"title":"Body Text","description":"The words, as plain text"},"body_html":{"anyOf":[{"type":"string","maxLength":500000},{"type":"null"}],"title":"Body Html","description":"The same as HTML, if you have it. It is cleaned before it is stored: scripts, styles and anything else a mail may not carry are removed"},"attachments":{"items":{"type":"string"},"type":"array","maxItems":10,"title":"Attachments","description":"Ids from `POST /v1/uploads`; only your own, not yet used ones","examples":[["0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6"]]}},"type":"object","required":["body_text"],"title":"FirstMessageIn","description":"What the customer wrote."},"Group":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"}},"type":"object","required":["id","name"],"title":"Group","examples":[{"id":"0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6","name":"Support"}]},"GroupList":{"properties":{"items":{"items":{"$ref":"#/components/schemas/Group"},"type":"array","title":"Items"}},"type":"object","required":["items"],"title":"GroupList","examples":[{"items":[{"id":"0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6","name":"Support"}]}]},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"Me":{"properties":{"key":{"$ref":"#/components/schemas/MeKey"},"tenant":{"$ref":"#/components/schemas/MeTenant"},"scopes":{"items":{"type":"string","enum":["cases:read","cases:write","cases:reply","contacts:read","contacts:write","webhooks:manage","knowledge:read","knowledge:write"]},"type":"array","title":"Scopes","description":"What the key may do"},"all_groups":{"type":"boolean","title":"All Groups","description":"The key sees every group's cases"},"groups":{"items":{"$ref":"#/components/schemas/MeGroup"},"type":"array","title":"Groups","description":"The groups it sees; empty with `all_groups`"}},"type":"object","required":["key","tenant","scopes","all_groups","groups"],"title":"Me","description":"Who is calling, so an integration can check its setup.","examples":[{"all_groups":false,"groups":[{"id":"0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f8","name":"Support"}],"key":{"id":"0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6","name":"Contact form","prefix":"nolmo_live_k3J9fQ2a"},"scopes":["cases:read","cases:write"],"tenant":{"id":"0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f7","name":"Furu & Lin","slug":"furu-lin"}}]},"MeGroup":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"}},"type":"object","required":["id","name"],"title":"MeGroup"},"MeKey":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"prefix":{"type":"string","title":"Prefix","description":"`nolmo_live_` and the first eight characters of the key"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At","description":"When the key stops working; null for never"}},"type":"object","required":["id","name","prefix","expires_at"],"title":"MeKey"},"MeTenant":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"slug":{"type":"string","title":"Slug"}},"type":"object","required":["id","name","slug"],"title":"MeTenant"},"Message":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"kind":{"type":"string","enum":["customer","note","reply"],"title":"Kind","description":"`customer`, `reply` (public, from the team, a key or the AI) or `note` (internal; only when asked for)"},"author":{"$ref":"#/components/schemas/Author"},"body_text":{"type":"string","title":"Body Text"},"body_html":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Body Html"},"attachments":{"items":{"$ref":"#/components/schemas/Attachment"},"type":"array","title":"Attachments"},"delivery":{"anyOf":[{"type":"string","enum":["queued","sent","failed"]},{"type":"null"}],"title":"Delivery","description":"For a reply that leaves by email: where it is. Null for everything else"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","kind","author","body_text","body_html","attachments","delivery","created_at"],"title":"Message","examples":[{"attachments":[],"author":{"name":"Astrid","type":"team"},"body_text":"Hi Kari, we are sending new tiles today.","created_at":"2026-11-09T10:30:00Z","delivery":"sent","id":"0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6","kind":"reply"}]},"MessageData":{"properties":{"case":{"$ref":"#/components/schemas/PublicCase"},"message":{"$ref":"#/components/schemas/PublicMessage"}},"type":"object","required":["case","message"],"title":"MessageData"},"MessageIn":{"properties":{"kind":{"type":"string","enum":["customer","note","reply"],"title":"Kind","description":"`customer`: a message from the person the case is about; it reopens a solved case and is refused on a closed one. `note`: internal, for the team, authored by the key. `reply`: a public answer to the customer, sent through the case's channel as a team reply is; it needs the scope `cases:reply`"},"body_text":{"type":"string","maxLength":100000,"minLength":1,"title":"Body Text"},"body_html":{"anyOf":[{"type":"string","maxLength":500000},{"type":"null"}],"title":"Body Html","description":"Cleaned before it is stored, as in a new case"},"attachments":{"items":{"type":"string"},"type":"array","maxItems":10,"title":"Attachments","description":"Ids from `POST /v1/uploads`; only your own, not yet used ones"}},"type":"object","required":["kind","body_text"],"title":"MessageIn","description":"Something to add to a case.","examples":[{"body_text":"Any news on this? I still have not heard anything.","kind":"customer"},{"body_text":"Checked with the warehouse: the pack was damaged in transit.","kind":"note"}]},"MessageList":{"properties":{"items":{"items":{"$ref":"#/components/schemas/Message"},"type":"array","title":"Items"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor","description":"Send it as `after` for the next page; null on the last"}},"type":"object","required":["items","next_cursor"],"title":"MessageList","examples":[{"items":[{"attachments":[],"author":{"name":"Astrid","type":"team"},"body_text":"Hi Kari, we are sending new tiles today.","created_at":"2026-11-09T10:30:00Z","delivery":"sent","id":"0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6","kind":"reply"}]}]},"Organization":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"domains":{"items":{"type":"string"},"type":"array","title":"Domains","description":"Email domains whose people belong here, lowercased"},"external_ids":{"additionalProperties":{"type":"string"},"type":"object","title":"External Ids","description":"Its ids in your own systems, by the system's name"},"people":{"type":"integer","title":"People","description":"How many contacts belong to it"},"case_counts":{"$ref":"#/components/schemas/CaseCounts"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","domains","external_ids","people","case_counts","created_at","updated_at"],"title":"Organization","description":"A company the workspace serves.","examples":[{"case_counts":{"cases":9,"last_contact_at":"2026-10-20T08:15:00Z","open":2},"created_at":"2026-09-02T10:00:00Z","domains":["fliser.no"],"external_ids":{"crm":"ORG-77"},"id":"0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f9","name":"Fliser AS","people":4,"updated_at":"2026-10-20T08:15:00Z"}]},"OrganizationIn":{"properties":{"name":{"type":"string","maxLength":200,"minLength":1,"title":"Name"},"domains":{"items":{"type":"string"},"type":"array","maxItems":50,"title":"Domains","description":"Email domains; a new contact with an address there joins the company"},"external_ids":{"additionalProperties":{"type":"string"},"type":"object","maxProperties":10,"title":"External Ids","description":"Its ids in your own systems, by the system's name"}},"additionalProperties":false,"type":"object","required":["name"],"title":"OrganizationIn","description":"A new company. One with the same name or the same id in another system is not made twice: the answer\nis 409 `organization_exists` with the existing company's id in `details.organization_id`.","examples":[{"domains":["fliser.no"],"external_ids":{"crm":"ORG-77"},"name":"Fliser AS"}]},"OrganizationList":{"properties":{"items":{"items":{"$ref":"#/components/schemas/Organization"},"type":"array","title":"Items"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor","description":"Send it as `after` for the next page; null on the last"}},"type":"object","required":["items","next_cursor"],"title":"OrganizationList","examples":[{"items":[{"case_counts":{"cases":9,"last_contact_at":"2026-10-20T08:15:00Z","open":2},"created_at":"2026-09-02T10:00:00Z","domains":["fliser.no"],"external_ids":{"crm":"ORG-77"},"id":"0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f9","name":"Fliser AS","people":4,"updated_at":"2026-10-20T08:15:00Z"}]}]},"OrganizationPatchIn":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":200,"minLength":1},{"type":"null"}],"title":"Name","description":"Never null"},"domains":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":50},{"type":"null"}],"title":"Domains","description":"Replaces the domains"},"external_ids":{"additionalProperties":{"anyOf":[{"type":"string"},{"type":"null"}]},"type":"object","maxProperties":10,"title":"External Ids","description":"Merged key by key: set, or forgotten with `null`"}},"additionalProperties":false,"type":"object","title":"OrganizationPatchIn","description":"What to change on a company. Fields left out are not touched.","examples":[{"domains":["fliser.no","fliser.com"],"external_ids":{}}]},"PublicCase":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"number":{"type":"integer","title":"Number","description":"The case's number in the workspace, the one people see and type"},"subject":{"type":"string","title":"Subject"},"status":{"type":"string","enum":["new","open","pending","hold","solved","closed"],"title":"Status"},"priority":{"type":"string","enum":["low","normal","high","urgent"],"title":"Priority"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Type","description":"The case type's key, when the case has one"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"assignee":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Assignee","description":"First name of whoever has the case; null when nobody does"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"contact":{"$ref":"#/components/schemas/PublicContact"},"channel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Channel","description":"How the case came in: `email`, `chat`, `api`, `messenger`, …"}},"type":"object","required":["id","number","subject","status","priority","type","tags","assignee","created_at","updated_at","contact","channel"],"title":"PublicCase","description":"A case as `/v1` shows it."},"PublicContact":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email","description":"The contact's address, when they have one"}},"type":"object","required":["id","name","email"],"title":"PublicContact"},"PublicMessage":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"kind":{"type":"string","enum":["public","internal"],"title":"Kind","description":"`public` is a reply the customer sees; `internal` is a note for the team"},"text":{"type":"string","title":"Text"},"author_kind":{"type":"string","enum":["customer","team","ai","system"],"title":"Author Kind"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","kind","text","author_kind","created_at"],"title":"PublicMessage","description":"A message on a case as `/v1` shows it."},"Replay":{"properties":{"since":{"type":"string","format":"date-time","title":"Since"}},"type":"object","required":["since"],"title":"Replay","description":"Send every event since a time again, in order, as new attempts with the same ids.","examples":[{"since":"2026-11-10T08:00:00Z"}]},"Replayed":{"properties":{"queued":{"type":"integer","title":"Queued","description":"How many events will be sent again"}},"type":"object","required":["queued"],"title":"Replayed","examples":[{"queued":12}]},"Tag":{"properties":{"tag":{"type":"string","title":"Tag"},"count":{"type":"integer","title":"Count","description":"How many of the cases the key sees have it"}},"type":"object","required":["tag","count"],"title":"Tag","examples":[{"count":12,"tag":"delivery"}]},"TagList":{"properties":{"items":{"items":{"$ref":"#/components/schemas/Tag"},"type":"array","title":"Items"}},"type":"object","required":["items"],"title":"TagList","examples":[{"items":[{"count":12,"tag":"delivery"}]}]},"Upload":{"properties":{"id":{"type":"string","title":"Id","description":"Name it in `attachments` of a case or a message"},"name":{"type":"string","title":"Name"},"content_type":{"type":"string","title":"Content Type"},"size":{"type":"integer","title":"Size","description":"Bytes"}},"type":"object","required":["id","name","content_type","size"],"title":"Upload","description":"A file waiting to be put on a message.","examples":[{"content_type":"image/jpeg","id":"0192f3c4-6a1b-7c2d-8e3f-a1b2c3d4e5f6","name":"damaged-tiles.jpg","size":183204}]},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"WebhookDelivery":{"properties":{"id":{"type":"string","format":"uuid","title":"Id","description":"The event's id, as the receiver got it in `webhook-id`"},"event":{"type":"string","enum":["case.created","case.updated","case.message.created","case.note.created"],"title":"Event"},"case_number":{"type":"integer","title":"Case Number"},"status":{"type":"string","enum":["pending","delivered","failed"],"title":"Status","description":"`pending`: to be sent or being retried; `delivered`: answered 2xx; `failed`: given up after 24 hours"},"attempts":{"type":"integer","title":"Attempts"},"response_code":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Response Code","description":"The receiver's last status code, when it answered"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error","description":"Why the last attempt failed when there was no answer: `timeout`, `unreachable`, `address_not_public`, …"},"occurred_at":{"type":"string","format":"date-time","title":"Occurred At"},"last_attempt_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Attempt At"},"next_attempt_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Next Attempt At"},"delivered_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Delivered At"}},"type":"object","required":["id","event","case_number","status","attempts","response_code","error","occurred_at","last_attempt_at","next_attempt_at","delivered_at"],"title":"WebhookDelivery","description":"One event for one endpoint, as the log shows it (kept 30 days).","examples":[{"attempts":1,"case_number":1042,"delivered_at":"2026-11-10T08:20:42Z","event":"case.message.created","id":"0192f3a4-2222-7e2d-a3f4-5b6c7d8e9f01","last_attempt_at":"2026-11-10T08:20:42Z","occurred_at":"2026-11-10T08:20:41Z","response_code":200,"status":"delivered"}]},"WebhookDeliveryList":{"properties":{"items":{"items":{"$ref":"#/components/schemas/WebhookDelivery"},"type":"array","title":"Items"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"}},"type":"object","required":["items","next_cursor"],"title":"WebhookDeliveryList","examples":[{"items":[{"attempts":1,"case_number":1042,"delivered_at":"2026-11-10T08:20:42Z","event":"case.message.created","id":"0192f3a4-2222-7e2d-a3f4-5b6c7d8e9f01","last_attempt_at":"2026-11-10T08:20:42Z","occurred_at":"2026-11-10T08:20:41Z","response_code":200,"status":"delivered"}]}]},"WebhookEndpoint":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"url":{"type":"string","title":"Url"},"events":{"items":{"type":"string","enum":["case.created","case.updated","case.message.created","case.note.created"]},"type":"array","title":"Events"},"enabled":{"type":"boolean","title":"Enabled"},"disabled_reason":{"anyOf":[{"type":"string","enum":["failing","manual"]},{"type":"null"}],"title":"Disabled Reason","description":"`failing`: it did not answer for three days; `manual`: someone turned it off"},"disabled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Disabled At"},"all_groups":{"type":"boolean","title":"All Groups","description":"Hears every case, whatever its group"},"group_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Group Ids","description":"The groups it hears; empty with `all_groups`"},"previous_secret_until":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Previous Secret Until","description":"While set, the secret that was rotated out still signs beside the new one, until this time"},"failing_since":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Failing Since","description":"Since when no send has been answered with a 2xx"},"last_success_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Success At"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","name","url","events","enabled","disabled_reason","disabled_at","all_groups","group_ids","previous_secret_until","failing_since","last_success_at","created_at"],"title":"WebhookEndpoint","description":"Where events are sent. The secret is not here: it is shown once, when the endpoint is made or its\nsecret rotated.","examples":[{"all_groups":false,"created_at":"2026-11-09T12:00:00Z","enabled":true,"events":["case.created","case.updated","case.message.created"],"group_ids":["0b1c1f0e-8f6e-4d8e-9a47-0c8f5d0e6a11"],"id":"0192f3a4-1111-7e2d-a3f4-5b6c7d8e9f01","last_success_at":"2026-11-10T08:20:42Z","name":"Returns page","url":"https://returns.example.com/hooks/nolmo"}]},"WebhookEndpointCreate":{"properties":{"name":{"type":"string","maxLength":120,"minLength":1,"title":"Name","description":"What the receiver is, for the list"},"url":{"type":"string","maxLength":2000,"title":"Url","description":"`https://` only, to a public address; no redirects are followed"},"events":{"items":{"type":"string","enum":["case.created","case.updated","case.message.created","case.note.created"]},"type":"array","minItems":1,"title":"Events"},"all_groups":{"type":"boolean","title":"All Groups","default":false},"group_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Group Ids"}},"type":"object","required":["name","url"],"title":"WebhookEndpointCreate","examples":[{"all_groups":false,"events":["case.created","case.updated","case.message.created"],"group_ids":["0b1c1f0e-8f6e-4d8e-9a47-0c8f5d0e6a11"],"name":"Returns page","url":"https://returns.example.com/hooks/nolmo"}]},"WebhookEndpointCreated":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"url":{"type":"string","title":"Url"},"events":{"items":{"type":"string","enum":["case.created","case.updated","case.message.created","case.note.created"]},"type":"array","title":"Events"},"enabled":{"type":"boolean","title":"Enabled"},"disabled_reason":{"anyOf":[{"type":"string","enum":["failing","manual"]},{"type":"null"}],"title":"Disabled Reason","description":"`failing`: it did not answer for three days; `manual`: someone turned it off"},"disabled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Disabled At"},"all_groups":{"type":"boolean","title":"All Groups","description":"Hears every case, whatever its group"},"group_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Group Ids","description":"The groups it hears; empty with `all_groups`"},"previous_secret_until":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Previous Secret Until","description":"While set, the secret that was rotated out still signs beside the new one, until this time"},"failing_since":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Failing Since","description":"Since when no send has been answered with a 2xx"},"last_success_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Success At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"secret":{"type":"string","title":"Secret","description":"Signs every send (`whsec_…`). Shown here and never again; keep it where the receiver can read it"}},"type":"object","required":["id","name","url","events","enabled","disabled_reason","disabled_at","all_groups","group_ids","previous_secret_until","failing_since","last_success_at","created_at","secret"],"title":"WebhookEndpointCreated","examples":[{"all_groups":false,"created_at":"2026-11-09T12:00:00Z","enabled":true,"events":["case.created","case.updated","case.message.created"],"group_ids":["0b1c1f0e-8f6e-4d8e-9a47-0c8f5d0e6a11"],"id":"0192f3a4-1111-7e2d-a3f4-5b6c7d8e9f01","last_success_at":"2026-11-10T08:20:42Z","name":"Returns page","secret":"whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw9o7cXx1b0hE=","url":"https://returns.example.com/hooks/nolmo"}]},"WebhookEndpointList":{"properties":{"items":{"items":{"$ref":"#/components/schemas/WebhookEndpoint"},"type":"array","title":"Items"}},"type":"object","required":["items"],"title":"WebhookEndpointList","examples":[{"items":[{"all_groups":false,"created_at":"2026-11-09T12:00:00Z","enabled":true,"events":["case.created","case.updated","case.message.created"],"group_ids":["0b1c1f0e-8f6e-4d8e-9a47-0c8f5d0e6a11"],"id":"0192f3a4-1111-7e2d-a3f4-5b6c7d8e9f01","last_success_at":"2026-11-10T08:20:42Z","name":"Returns page","url":"https://returns.example.com/hooks/nolmo"}]}]},"WebhookEndpointUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":120,"minLength":1},{"type":"null"}],"title":"Name"},"url":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Url"},"events":{"anyOf":[{"items":{"type":"string","enum":["case.created","case.updated","case.message.created","case.note.created"]},"type":"array","minItems":1},{"type":"null"}],"title":"Events"},"enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Enabled"},"all_groups":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"All Groups"},"group_ids":{"anyOf":[{"items":{"type":"string","format":"uuid"},"type":"array"},{"type":"null"}],"title":"Group Ids"}},"type":"object","title":"WebhookEndpointUpdate","description":"Only what is sent changes. Turning an endpoint on clears its failing mark.","examples":[{"enabled":false}]}},"securitySchemes":{"HTTPBearer":{"type":"http","description":"An API key from Settings → API keys","scheme":"bearer","bearerFormat":"nolmo_live_…"}}}}