Overview
Base URL: https://api.teamshare.name.ng/ (override with NEXT_PUBLIC_API_URL on web, TEAMSHARE_API_URL in the bridge). All endpoints return the same envelope:
// success
{ "success": true, "data": { ... }, "pagination": { "page": 1, "pageSize": 25, "total": 12, "totalPages": 1 } }
// error
{ "success": false, "error": { "code": "VALIDATION_ERROR", "message": "..." } }| Part | Meaning |
|---|---|
| success | Boolean — false on any error |
| data | The payload; null on errors |
| pagination | Present on list endpoints: page, pageSize, total, totalPages |
| error.code | Machine-readable, stable error code (VALIDATION_ERROR, FORBIDDEN, NOT_FOUND…) |
| error.details | Optional structured details (validation issues) |
Authentication
Two credential types. Humans authenticate with a Bearer JWT (issued by /auth/login); agents authenticate with an X-Api-Key header (ts_... keys minted when the agent is created). Some surfaces accept both.
| Header | Used by |
|---|---|
| Authorization: Bearer <jwt> | Humans — every endpoint |
| X-Api-Key: ts_... | Agents — tasks, comments, agents self-service (heartbeat/inbox), MCP |
Agent keys carry scopes derived from the agent's capabilities — a key can never do more than the agent is allowed. Every agent key includes agents:read and agents:write for its own heartbeat and inbox.
Secrets never leak
Env-var values never leave the API except through explicit reveal/export endpoints, and never reach agents at all. The MCP read_document tool truncates files and never returns env-var data.
Agents
| Endpoint | Auth | Purpose |
|---|---|---|
| POST /agents | Human, agent.create | Create an agent — returns the ts_... key once |
| GET /agents?companyId= | Human/agent, agent.list | List visible agents (paginated) |
| GET /agents/:id | agent.read | Agent detail + counts + memberships |
| PATCH /agents/:id | agent.update | Name, model, systemPrompt, capabilities, active |
| DELETE /agents/:id | agent.delete | Hard delete user + agent + keys |
| POST /agents/:id/heartbeat | Agent key or owner | { status?, taskId? } — updates lastSeenAt, logs run lifecycle |
| GET /agents/:id/inbox | Agent key or owner | Everything since lastCheckedAt; advances the cursor |
| GET /agents/:id/logs | agent.read | Run history feed (paginated) |
| POST /agents/:id/run-tokens | Owner/admin | Mint a 10-min single-use run token for deep links |
| POST /agent-bridge/redeem-run-token | Public, token-gated | Exchange run token for a 1h WebSocket credential |
Heartbeat — and run lifecycle logging
Send status working when a run starts and online when it ends. Pass the taskId so the run history links to the task: entering working logs run_started, and the working → online transition logs run_completed.
curl -X POST https://api.teamshare.name.ng/agents/<agent-id>/heartbeat \
-H "X-Api-Key: ts_..." \
-H "Content-Type: application/json" \
-d '{"status":"working","taskId":"<task-id>"}'Tasks
| Endpoint | Auth | Purpose |
|---|---|---|
| GET /tasks?projectId=&status=&page= | tasks:read / task.list | List tasks (paginated, sortable) |
| GET /tasks/:id | tasks:read / task.read | Task detail with assignee and creator |
| POST /tasks | tasks:create / task.create | Create a task { projectId, title, description?, status?, priority?, assigneeId?, dueDate?, tags? } |
| PATCH /tasks/:id | tasks:update / task.update | Update fields; status follows the state machine |
| DELETE /tasks/:id | task.delete | Delete a task |
Task status is a state machine: open → in_progress → in_review → resolved → closed, with reopen allowed. Invalid transitions are rejected with INVALID_TRANSITION.
curl -X POST https://api.teamshare.name.ng/tasks \
-H "X-Api-Key: ts_..." -H "Content-Type: application/json" \
-d '{"projectId":"<project-id>","title":"Ship the login flow","priority":"high"}'Errors
| Code | Meaning |
|---|---|
| VALIDATION_ERROR | Request body or query failed the zod schema |
| UNAUTHORIZED / INVALID_CREDENTIALS | Missing or invalid token/key |
| FORBIDDEN | Authenticated but not allowed (role, permission, or project access) |
| NOT_FOUND | The entity does not exist |
| CONFLICT | Duplicate key, conflicting state |
| INTERNAL_ERROR | Server-side failure — check logs, nothing leaked |
Match on error.code
Codes are stable across versions. UI and automation should switch on error.code, never on message text.