Get started
Requests and responses
JSON in, JSON out, over HTTPS. This page covers the conventions every endpoint shares: ids, times, money, partial updates, languages and request ids.
JSON
- Send request bodies as one JSON object with
Content-Type: application/json. Responses areapplication/json; charset=utf-8. - Bodies are limited to 1 MB (
body_too_large). - Unknown fields are rejected, not ignored: a misspelled field answers
400unknown_fieldwith the field named infields. Send only the fields an endpoint documents, never whole objects copied from a response. - A value of the wrong type (a string where a number is expected) answers
400bad_json. - Creating returns
201 Createdwith the new object. Reading and changing return200 OK. Deleting returns200 OKwith a small confirmation such as{"ok": true, "id": "lead_…"}or{"id": "hook_…", "deleted": true}.
Ids
Every id is a string made of a type prefix, an underscore and 26 lowercase letters and digits, for example lead_01j8z7c2d4f6g8h0j2k4m6n8p0. The prefix tells you what the id points to:
| Prefix | Object | Prefix | Object |
|---|---|---|---|
lead_ | Lead | task_ | Task |
contact_ | Contact | note_ | Note |
company_ | Company | invoice_ | Invoice |
pipeline_ | Pipeline | product_ | Product |
stage_ | Stage | field_ | Custom field |
conv_ | Conversation | msg_ | Message |
channel_ | Channel | member_ | Member of the workspace |
hook_ | Webhook | dlv_ | Webhook delivery |
key_ | API key | ws_ | Workspace |
app_ | App (its OAuth client id) | inst_ | App installation |
Ids are sortable by creation time and never reused. Treat them as opaque strings: store them as they are and compare them exactly. Leads also have a human number (#1042) that is unique in the workspace.
An id of the wrong type in a path answers 404 not_found or 400 invalid_id_type.
Times
Times are RFC 3339 strings with fractional seconds, for example "2026-09-27T09:41:12.482913Z". Use a real RFC 3339 parser: the number of fractional digits varies. Fields that can be empty are null, for example closed_at of an open lead. When you send a time (a task's due_at), include the offset.
Money
Amounts are integers in the smallest unit of their currency, next to a three-letter currency code. For Uzbek soʻm that unit is the tiyin: 1 soʻm is 100 tiyin, so 1,500,000 soʻm is sent and returned as 150000000.
{ "amount": 150000000, "currency": "UZS" }This applies to a lead's amount, a product's price, and an invoice's amount, paid_amount and line price. Never send amounts as decimals or strings. A lead without a currency uses the workspace's currency.
Partial updates
PATCH changes only the fields you send; every other field keeps its value.
- To clear a reference such as a lead's
owner_id,contact_idorcompany_id, send it asnull. customholds the values of custom fields, keyed by the field'skey. In a PATCH, only the keys you send change.- Names that Kweko shows in several languages (pipelines, stages, loss reasons, field labels) are objects keyed by locale, for example
{"uz-Latn": "Yangi", "ru": "Новая", "en": "New"}. When you write one, you can send a plain string: it is used for every language.
Deleting and restoring
Deleting a lead, contact or company moves it to the trash: it disappears from lists, reading it answers 410 gone with deleted_at, and POST /v1/{leads|contacts|companies}/{id}/restore brings it back.
Languages
Error messages and a few labels follow the Accept-Language header: English (en, the default), Russian (ru) or Uzbek (uz). Codes such as validation_failed and field names never change with the language, so branch on codes, not on messages.
Request ids
Every response has an X-Request-Id header, and every error body repeats it as request_id. Quote it when you contact support. You can send your own X-Request-Id (up to 64 letters, digits, -, _ or .) to trace a call across your systems; Kweko uses and returns it.
Retries and idempotency
The API has no general Idempotency-Key header yet.
GETrequests are always safe to retry.- Sending a message accepts a
client_id(up to 64 characters): a retry with the sameclient_idreturns the message that was already queued instead of sending it twice. See Conversations. - For other writes, a retry after a timeout can create a duplicate. Look the record up first (for example by your own reference in
sourceor a custom field) or accept the rare duplicate. - Retry
429and5xxanswers with exponential backoff; for429, wait at leastRetry-Afterseconds.
Versioning
The version is in the path (/v1). Within v1, new fields, endpoints, event types and error codes can appear at any time; changes that would break an integration are meant for a new version. Write your code to ignore unknown fields and to handle unknown error codes by their HTTP status. Changes are listed in the changelog.