DOCS

API Reference

Code Corgi REST API — authenticate, trigger scans, retrieve findings, and manage policies programmatically.

API Reference

The Code Corgi API is a REST API. All endpoints are under:

https://api.phantomcorgi.com/v1

Authentication

All API requests require a bearer token. Generate tokens in the dashboard under Settings → API Tokens.

Authorization: Bearer gz_live_xxxxxxxxxxxxxxxxxxxx

Tokens are scoped to an organisation. A token with the read scope can retrieve findings; a token with the write scope can also trigger scans and update policy.

Endpoints

Scans

Trigger a scan

POST /v1/scans

Trigger an on-demand scan of a pull request diff.

Request body

{
  "repository": "acme/backend",
  "pr_number": 142,
  "commit_sha": "a1b2c3d4e5f6..."
}

Response 202 Accepted

{
  "scan_id": "scan_01J2K3L4M5N6P7Q8R9S0T1U2V3",
  "status": "queued",
  "repository": "acme/backend",
  "pr_number": 142,
  "created_at": "2026-03-27T10:00:00Z"
}

Get scan status

GET /v1/scans/{scan_id}

Response 200 OK

{
  "scan_id": "scan_01J2K3L4M5N6P7Q8R9S0T1U2V3",
  "status": "complete",
  "repository": "acme/backend",
  "pr_number": 142,
  "commit_sha": "a1b2c3d4...",
  "started_at": "2026-03-27T10:00:01Z",
  "completed_at": "2026-03-27T10:00:04Z",
  "findings_count": 2
}

Status values: queued | processing | complete | failed

List scans

GET /v1/scans?repository=acme/backend&limit=20&cursor=...

Returns scans in reverse chronological order. Supports cursor-based pagination.


Findings

List findings for a scan

GET /v1/scans/{scan_id}/findings

Response 200 OK

{
  "findings": [
    {
      "finding_id": "fnd_01J2K3...",
      "scan_id": "scan_01J2K3...",
      "severity": "high",
      "category": "unicode",
      "rule": "bidi_override",
      "file": "src/auth/middleware.ts",
      "line": 42,
      "column": 17,
      "description": "Bidirectional override character U+202E detected in identifier 'checkAcce‮ss'",
      "dismissed": false,
      "created_at": "2026-03-27T10:00:03Z"
    }
  ],
  "next_cursor": null
}

Dismiss a finding

POST /v1/findings/{finding_id}/dismiss

Request body

{
  "reason": "Test fixture — not production code"
}

Response 200 OK

Dismissals are recorded in the audit log with the token owner’s identity.


Policy

Get organisation policy

GET /v1/policy

Returns the active policy configuration for the organisation.

Update policy

PUT /v1/policy

Request body — same structure as phantomcorgi.yaml detection and policy sections.


Audit log

List audit events

GET /v1/audit?limit=50&cursor=...

Returns audit events in reverse chronological order. Events include:

  • scan.created — a scan was triggered
  • scan.completed — a scan completed
  • finding.created — a finding was raised
  • finding.dismissed — a finding was dismissed
  • policy.updated — organisation policy was changed
  • token.created / token.revoked — API token lifecycle events

Webhooks

Code Corgi can POST events to your endpoint as scans complete.

Registering a webhook

In the dashboard under Settings → Webhooks, add your endpoint URL and choose which events to receive.

Payload signature

All webhook payloads are signed with HMAC-SHA256. Verify the signature before processing:

import { createHmac } from 'crypto';

function verifyWebhook(payload: string, signature: string, secret: string): boolean {
  const expected = createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  return `sha256=${expected}` === signature;
}

// In your handler:
const sig = req.headers['x-phantomcorgi-signature'];
const raw = req.rawBody; // unparsed string body
if (!verifyWebhook(raw, sig, process.env.WEBHOOK_SECRET)) {
  return res.status(401).end();
}

Event payload

{
  "event": "scan.completed",
  "scan_id": "scan_01J2K3...",
  "repository": "acme/backend",
  "pr_number": 142,
  "findings_count": 2,
  "status": "complete",
  "timestamp": "2026-03-27T10:00:04Z"
}

Rate limits

TierRequests / minute
Free30
Pro300
EnterpriseCustom

Rate limit headers are returned on every response:

X-RateLimit-Limit: 300
X-RateLimit-Remaining: 298
X-RateLimit-Reset: 1743070860

Errors

All errors return a JSON body:

{
  "error": {
    "code": "not_found",
    "message": "Scan scan_01J2K3... not found"
  }
}
HTTP statuscodeMeaning
400invalid_requestMalformed request body or missing required field
401unauthorizedMissing or invalid token
403forbiddenToken lacks required scope
404not_foundResource does not exist
429rate_limitedToo many requests
500internal_errorCode Corgi server error