Navigation

Authentication & Limits

API keys

Every API call authenticates with a workspace-scoped API key in the Authorization header:

curl -H "Authorization: Bearer kdt_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
     https://api.konduit.work/v1/me

Keys live in Workspace Settings → API Keys. Treat them like passwords — anyone with a key can read and write everything the key has access to. Revoke and rotate via the same UI.

If billing lapses (payment failure, plan expiry), API keys keep working through the configured grace period (default 14 days), then return 403.

Key types

  • Master keys (scopes = *) — full read/write on every resource. Can edit/delete comments and time entries authored by any user.
  • Scoped keys — restricted to specific resources or actions (read-only, particular tables, etc.). Can only edit/delete comments and time entries authored by the API key creator.

Plan limits

Free Pro Business
API access
API keys 0 3 10
Calls / month 0 50,000 500,000
Calls / minute 0 600 6,000
Bulk insert / minute (sync) 0 5 20
Bulk rows / request (sync) 0 250 250
Bulk rows / job (async) 0 50,000 50,000
Concurrent bulk jobs 0 1 5

Each plan also includes an auto-generated master key in addition to the keys above. All keys in a workspace share the same monthly + per-minute call budget — adding keys doesn't increase throughput. To scale call volume, use the API call add-on packs.

CORS

Public API endpoints respond with:

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PATCH, DELETE, OPTIONS
Access-Control-Allow-Headers: Authorization, Content-Type
Access-Control-Expose-Headers: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, Retry-After

This means you can call the API directly from a browser-based integration without a server-side proxy. Authorization comes from the Authorization: Bearer kdt_... header you supply, not the request origin.

Access-Control-Allow-Credentials is never set. Cookies are not sent cross-origin. The Bearer token is the only credential.

Rate limit headers

Every response includes:

Header Meaning
X-RateLimit-Limit Calls allowed per minute for your plan
X-RateLimit-Remaining Calls remaining in the current window
X-RateLimit-Reset Unix timestamp when the window resets
Retry-After Seconds to wait (only sent on 429)

When you exceed the per-minute or monthly limit, the API returns 429 with a Retry-After header. Use exponential backoff and respect Retry-After.

HTTP/1.1 429 Too Many Requests
Retry-After: 12
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1735689660

{ "error": "Rate limit exceeded" }

Bulk insert rate limits

Synchronous bulk inserts (POST /datatables/{tableId}/rows/bulk) have their own per-minute limit (bulkInsertPerMinute) on top of the general per-minute limit. A single sync bulk request can contain up to bulkRowsPerRequest rows.

For larger imports, use the async bulk job endpoint (POST /datatables/{tableId}/jobs/insert) — up to 50,000 rows in one submission, processed in the background, polled via GET /jobs/{jobId}. Concurrent jobs per workspace are capped (Pro=1, Business=5).

For data loads larger than 50k rows in one go, use the in-app CSV import — it bypasses all per-job caps and runs as a background job.

Next