API, Git and AI integrations
Connect the REST API, GitHub or GitLab, and hosted MCP for Codex and Claude Code to your organization context.
Getting started
The API is REST over HTTPS and returns JSON. Every request is scoped to one organization by its API key.
1. Create an API key
In the app, open Settings → API keys and create a key. Copy it once - it is shown only at creation. Keys look like pos_sk_….
2. Base URL & authentication
Send your key in the x-api-key header on every request. The base URL is:
https://app.workthroughline.com/api/v13. Make your first request
List your work items:
curl https://app.workthroughline.com/api/v1/work-items \
-H "x-api-key: pos_sk_your_key_here"GitHub and GitLab integration
WorkThroughLine connects engineering activity to delivery context without storing a provider access token. Every repository gets a unique webhook URL and secret.
- Connect a repository under Settings → GitHub / GitLab and choose optional status automations.
- Add the generated webhook URL and secret in the provider. For GitHub choose application/json plus Push and Pull request events; for GitLab choose Push and Merge request events.
- Put the work-item key in a branch name, commit message or PR/MR. WTL automatically shows the branch, commit and review on the card.
Example linking convention
feature/WI-42-checkout-fix
git commit -m "WI-42 handle declined cards"
Pull request: "WI-42 Checkout reliability"Result: developers and PMs see what is open, merged and on which branch directly on the work item, with a link back to GitHub or GitLab.
MCP for Codex and Claude Code
Each ADMIN, PM or DEV creates one personal API key. The client sends it with every MCP request, and WTL applies the same role, maker rules and tenant isolation as the app.
Codex - set PRODUCT_OS_API_KEY in the environment, then register the hosted server:
codex mcp add workthroughline --url https://mcp.workthroughline.com/mcp --bearer-token-env-var PRODUCT_OS_API_KEYClaude Code - use the same environment key without writing the secret into configuration:
claude mcp add-json --scope user workthroughline '{"type":"http","url":"https://mcp.workthroughline.com/mcp","headers":{"x-api-key":"${PRODUCT_OS_API_KEY}"}}'What the AI can use
Goals and their explanations, OKRs and key results, interviews, transcripts, summaries, analyses and insights, opportunities, solutions, experiments, all work items, sprints, relations, comments and GitHub/GitLab artifacts. get_discovery_context returns one paginated, evidence-first packet.
Example discovery request
Analyse every interview and analysis, review the active product goals and OKRs, check existing opportunities, solutions and experiments, then propose missing solutions with supporting evidence. Do not create anything until I approve.Conventions
Authentication
Pass x-api-key on every request. A key acts with the role it was created for and is bound to its organization.
Rate limit
100 requests per minute per client. Exceeding it returns HTTP 429.
Errors
Non-2xx responses return JSON { "error", "message" } and, for validation errors, a details object.
Pagination
Large lists are cursor-paginated: pass ?cursor=… &limit=… and follow nextCursor until it is null.
Webhooks
Subscribe an HTTPS endpoint to events and we POST a signed JSON payload when they happen. Delivery is retried with exponential backoff.
Event types
work_item.createdA work item was created.work_item.updatedA work item was edited.work_item.status_changedA work item moved to a new status (payload adds `previousStatus`).ckr.createdAn OKR was created.ckr.updatedAn OKR was edited.opportunity.createdA discovery opportunity was created.experiment.concludedAn experiment was concluded (SUCCEEDED / FAILED / INCONCLUSIVE).intake.createdA stakeholder submitted intake (no submitter contact is ever sent).changelog.publishedA changelog entry was published.Payload
Every delivery is a versioned envelope. id is shared across all endpoints for one event - use it as an idempotency key.
{
"id": "b3f1c2e4-0000-0000-0000-000000000000",
"event": "work_item.status_changed",
"apiVersion": "2026-07-13",
"createdAt": "2026-07-13T10:00:00.000Z",
"organizationId": "a1b2c3d4-0000-0000-0000-000000000000",
"data": {
"id": "…",
"key": "WI-42",
"title": "Checkout crash",
"status": "DONE",
"previousStatus": "IN_REVIEW"
}
}Verify the signature
Each request carries X-WTL-Signature: sha256=<hmac>. Recompute the HMAC-SHA256 of the raw body with your webhook secret and compare in constant time.
import { createHmac, timingSafeEqual } from 'node:crypto';
function verify(rawBody, signature, secret) {
const expected = 'sha256=' + createHmac('sha256', secret).update(rawBody).digest('hex');
const a = Buffer.from(expected), b = Buffer.from(signature ?? '');
return a.length === b.length && timingSafeEqual(a, b);
}
// Express - note express.raw so you verify the EXACT bytes we signed:
app.post('/hooks/wtl', express.raw({ type: 'application/json' }), (req, res) => {
if (!verify(req.body, req.get('X-WTL-Signature'), process.env.WTL_WEBHOOK_SECRET))
return res.sendStatus(401);
const event = JSON.parse(req.body.toString());
// handle event.event / event.data … then ack quickly
res.sendStatus(200);
});Endpoints
curl -X POST https://app.workthroughline.com/api/v1/webhooks \
-H "x-api-key: pos_sk_your_key_here" \
-H "content-type: application/json" \
-d '{"url":"https://example.com/hooks/wtl","events":["work_item.status_changed"]}'