REST API
A JSON REST API for reading and writing everything in your Kyo workspace — deals, people, companies, tasks, pipelines, spaces, and more. Requests are authenticated with OAuth 2.0 access tokens and enforced by the same permissions the Kyo app uses.
Base URL
https://pvozbkuhjofzitsmpspf.supabase.co/functions/v1/api-v1/v1
All paths on this page are relative to this base. The API is HTTPS-only, and every request
and response body is JSON. Breaking changes only ship under a new version prefix —
/v1 paths stay stable.
Authentication
Every request carries two headers:
GET /v1/deals
Authorization: Bearer kyo_at_…
apikey: <public anon key>
Authorization— a Kyo access token (prefixkyo_at_) obtained through the OAuth 2.0 flow. Access tokens expire after 1 hour; refresh tokens rotate on every use.apikey— a public routing key, the same value the Kyo web app ships. It grants nothing by itself; all authorization comes from the bearer token.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InB2b3pia3Voam9meml0c21wc3BmIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NzUwMzU0ODMsImV4cCI6MjA5MDYxMTQ4M30.PccqZEYqEHdG1dnFn1AtCcrBGSCqU5ptcP5Vxt-KhBY
Resources
Each resource requires its scope with :read for GET and
:write for POST/PATCH — see
scopes.
| Resource | Scope | Create requires | List filters |
|---|---|---|---|
/v1/deals | deals | name, pipeline_id | pipeline_id, pipeline_stage_id, owner_id, company_id |
/v1/people | people | name | company_id, email |
/v1/companies | companies | name | industry |
/v1/tasks | tasks | name | space_id, project_id, assignee_id, completed, is_private, stage_id |
/v1/deal_tasks | tasks | deal_id, name | deal_id, assignee_id, completed, is_private |
/v1/pipelines | pipelines | name | — |
/v1/pipeline_stages | pipelines | pipeline_id, name | pipeline_id |
/v1/labels | labels | name | — |
/v1/deal_people | deals | deal_id, person_id | deal_id, person_id |
/v1/deal_labels | deals | deal_id, label_id | deal_id, label_id |
/v1/comments | comments | entity_type, entity_id, content | entity_type, entity_id |
/v1/spaces | spaces | name | status, is_default |
/v1/projects | spaces | space_id, name | space_id |
/v1/activity (read only) | activity | — | entity_type, entity_id |
/v1/credits (read only) | credits | — | — |
/v1/enrich (POST only, metered) | enrich | domain | — |
Writable fields
Writes accept only the fields below; server-owned columns (workspace, creator) are always set server-side and can't be supplied in the body.
| Resource | Fields |
|---|---|
deals | name, pipeline_id, pipeline_stage_id, owner_id, value, confidence, website, instagram, twitter, notes, company_id |
people | name, company, company_id, phone, email, position, linkedin_url, twitter_url |
companies | name, website, instagram, linkedin, twitter, industry, size, notes |
tasks | name, space_id, project_id, assignee_id, due_date, start_date, priority (0–4), completed, description, is_private |
deal_tasks | deal_id, name, assignee_id, due_date, priority, completed, description, is_private |
pipelines | name, position |
pipeline_stages | pipeline_id, name, position, metric_tag |
spaces | name, image_url, is_default, status, notes |
projects | space_id, name, position, start_date, end_date, kanban_enabled |
labels | name |
comments | entity_type, entity_id, content |
deal_people | deal_id, person_id, is_primary |
deal_labels | deal_id, label_id |
pipeline_stages.metric_tagmust be one ofmessages_sent,responses,positive_responses,deals_closed.comments.entity_typemust bedealortask.
Reading data
GET /v1/<resource> lists records; GET /v1/<resource>/{id}
fetches one. (Junction resources — deal_people, deal_labels — and
credits have no /{id} form.)
curl "https://pvozbkuhjofzitsmpspf.supabase.co/functions/v1/api-v1/v1/deals?limit=20" \
-H "Authorization: Bearer kyo_at_…" \
-H "apikey: $KYO_ANON_KEY"
{
"data": [
{ "id": "…", "name": "Acme Corp", "value": 5000, "created_at": "…" }
],
"next_cursor": "MjAyNi0wNy0…"
}
Single reads, creates, and updates return { "data": { … } }.
Pagination
Lists use keyset cursors ordered by (created_at, id) descending — stable under
concurrent writes, no offsets.
limit— page size, default 50, max 200.cursor— thenext_cursorfrom the previous page.nullmeans you're on the last page.
GET /v1/deals?limit=100&cursor=MjAyNi0wNy0…
Filtering
Lists accept exact-match query parameters — the "List filters" column in the resources table:
GET /v1/tasks?completed=false&space_id=9a1f…
Writing data
Create
POST /v1/<resource> with a JSON body returns 201 and the created record:
curl -X POST "https://pvozbkuhjofzitsmpspf.supabase.co/functions/v1/api-v1/v1/deals" \
-H "Authorization: Bearer kyo_at_…" \
-H "apikey: $KYO_ANON_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "Acme Corp", "pipeline_id": "<uuid>", "value": 5000 }'
Update
PATCH /v1/<resource>/{id} with a partial body returns 200 and the updated record:
curl -X PATCH "https://pvozbkuhjofzitsmpspf.supabase.co/functions/v1/api-v1/v1/deals/<id>" \
-H "Authorization: Bearer kyo_at_…" \
-H "apikey: $KYO_ANON_KEY" \
-H "Content-Type: application/json" \
-d '{ "pipeline_stage_id": "<uuid>" }'
Deleting
There is no DELETE in v1 — it returns
405 method_not_allowed everywhere. Records can be created and updated, never
hard-deleted through the API.
The one exception is detaching a junction row. To unlink a person or label from a
deal, POST to the junction resource with ?detach=true (or
"_detach": true in the body). Requires deals:write:
curl -X POST "https://pvozbkuhjofzitsmpspf.supabase.co/functions/v1/api-v1/v1/deal_people?detach=true" \
-H "Authorization: Bearer kyo_at_…" \
-H "apikey: $KYO_ANON_KEY" \
-H "Content-Type: application/json" \
-d '{ "deal_id": "<uuid>", "person_id": "<uuid>" }'
Errors
Errors are JSON with a machine-readable code and a request id:
{
"error": "insufficient_scope",
"message": "…",
"request_id": "…"
}
| Status | Code | Meaning |
|---|---|---|
| 400 | bad_request | Malformed request, body, or cursor |
| 401 | unauthorized | Missing, invalid, expired, or revoked token |
| 402 | insufficient_credits | Workspace credit balance too low (enrichment) |
| 403 | insufficient_scope / forbidden | Token lacks the required scope, or permissions deny it |
| 404 | not_found / unknown_resource | No such record or resource |
| 405 | method_not_allowed | Method not supported (e.g. DELETE) |
| 422 | validation_error | Required field missing or value invalid |
| 429 | rate_limited | Rate limit exceeded — retry after Retry-After seconds |
| 5xx | internal_error / upstream_error | Something failed on Kyo's side |
Every response includes an X-Request-Id header — include it when reporting an
issue so we can trace the request.
Rate limits
- 60 requests / minute per token
- 600 requests / minute per workspace
Responses carry X-RateLimit-Remaining and X-RateLimit-Reset.
Exceeding a limit returns 429 rate_limited with Retry-After: 60.
Enrichment
POST /v1/enrich looks up firmographics for a company domain — name, website,
industry, and socials. This is the API's only metered endpoint: fresh
lookups spend workspace credits, and it requires the opt-in enrich:write scope.
curl -X POST "https://pvozbkuhjofzitsmpspf.supabase.co/functions/v1/api-v1/v1/enrich" \
-H "Authorization: Bearer kyo_at_…" \
-H "apikey: $KYO_ANON_KEY" \
-H "Content-Type: application/json" \
-d '{ "domain": "acme.com" }'
Returns 402 insufficient_credits when the workspace balance is too low.
Scopes
Scopes are resource:read / resource:write (the wildcard
resource:* is also accepted). A request without the required scope fails with
403 insufficient_scope. Scopes are granted by the user during the
OAuth flow and can never exceed what that user can do in the app.
| Scope | Grants |
|---|---|
deals:read / deals:write | Deals, plus their person and label links (deal_people, deal_labels) |
people:read / people:write | CRM contacts |
companies:read / companies:write | Companies |
tasks:read / tasks:write | Tasks, including deal tasks |
pipelines:read / pipelines:write | Pipelines and pipeline stages |
labels:read / labels:write | Labels |
comments:read / comments:write | Comments on deals and tasks |
spaces:read / spaces:write | Spaces and projects |
activity:read | The activity (audit) feed — read only |
credits:read | Workspace credit balance — read only |
enrich:write | Metered company enrichment |