Data API

Read-only access to your own data, for a spreadsheet, a dashboard or a nightly sync. Part of the Enterprise plan.

Last updated 11 August 2026

Get a key

An account admin creates keys under Settings → API access. Name each key after what will use it, and revoke it there when that thing is retired. The key is shown once; only its fingerprint is kept.

Send it as a bearer token on every request:

curl -H "Authorization: Bearer cfk_…" http://localhost:3000/api/v1/clients

Endpoints

All three take the same parameters and return the same shape.

GET /api/v1/clients

Your clients, with their pod, active project count and health score.

Columns · id, company_name, industry, website, country, contact_name, contact_email, pod, active_projects, health_score, created_at, updated_at

GET /api/v1/projects

Every project, with the client, pod, services, budget and how far along it is.

Columns · id, title, status, client_id, client_name, pod, services, start_date, deadline, budget, budget_currency, completion_pct, at_risk, risk_reason, open_tasks, created_at, updated_at

GET /api/v1/tasks

Every task, with who it is assigned to and which project and client it belongs to.

Columns · id, title, status, priority, project_id, project_title, client_name, assignees, due_date, completed_at, from_meeting, created_at, updated_at

Parameters

  • limit — rows per page, 1 to 1000. Default 100.
  • cursor — the next_cursor from the previous page. When it is null, that was the last page.
  • updated_since — an ISO 8601 instant. Only rows changed since then, which is what a nightly sync wants.
  • format=csv — a CSV file instead of JSON (or send Accept: text/csv). Opens cleanly in Excel and Google Sheets; the next cursor is in the X-Next-Cursor header.

Responses

JSON:

{
  "data": [ { "id": "…", "company_name": "…", … } ],
  "next_cursor": "clx…"        // null on the last page
}

Dates are ISO 8601 in UTC. Money is a number in the currency column beside it. Lists (services, assignees) are joined with a semicolon in CSV.

Errors come back as JSON with a plain-English message and the obvious status: 401 for a bad or revoked key, 400 for a bad parameter, 429 when a key goes over 1,000 requests an hour.

Examples

Everything changed in the last day, into a file:

curl -H "Authorization: Bearer $CFK" \
  "http://localhost:3000/api/v1/tasks?updated_since=$(date -u -d yesterday +%FT%TZ)&format=csv" \
  -o tasks.csv

Google Sheets, with the ImportJSON add-on or Apps Script:

const res = UrlFetchApp.fetch('http://localhost:3000/api/v1/projects?limit=1000', {
  headers: { Authorization: 'Bearer ' + PropertiesService.getScriptProperties().getProperty('CFK') },
})
const rows = JSON.parse(res.getContentText()).data

Power BI: Get data → Web, paste the URL, then under Advanced add the header Authorization with the value Bearer cfk_….

What it will not do

  • Change anything. There is no write access, and there will not be until someone needs it enough to say so.
  • Return another agency’s data. A key is bound to the agency that made it.
  • Return messages, files or client contact notes. Structured records only.

Something missing? Email support@trickleup.co.uk — or read how the data is protected on the security page.

Questions about this page? Get in touch and we’ll answer properly.