> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cantina.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Apex service API

> Run Apex from serverless functions, cron jobs, and internal audit hubs with an organization-scoped service key and a REST/JSON workflow.

* **Read:** 8 min
* **Updated:** July 10, 2026
* **Audience:** Platform engineers

## § 01 Choose the right integration

Use Apex CLI or MCP when a person or coding agent is working in a repository. Use the service API when a headless process needs HTTP, JSON, and a static organization credential.

|                 |                                                                    |
| --------------- | ------------------------------------------------------------------ |
| CLI + MCP       | Interactive developer and coding-agent workflows with device login |
| Service API     | Serverless workers, cron jobs, CI, and internal audit hubs         |
| Authentication  | Authorization: Bearer apex\_sk\_live\_… or X-API-Key               |
| Findings format | GitLab SAST JSON with stable finding IDs and source locations      |

The machine-readable contract is available at `/api/apex/v1/openapi.json`.

## § 02 Prerequisites

* Connect the GitHub repository and link it to an active workspace in the same Apex organization that owns the service key.
* Use a full 40- or 64-character Git commit SHA. Branch names and moving refs are not accepted.
* Create or revoke keys as an Apex organization manager or Bedrock administrator.
* Store the key in a secret manager. Apex displays the raw secret only once and stores only its hash.

> **Version-one repository support**
> The first service API release accepts GitHub repositories already connected to your Apex organization. GitLab service-account access will follow once connection ownership can be made explicit.

## § 03 Create a service key

```javascript theme={null}
apex update
apex login
# Read-only key for polling status and importing findings:
apex service-key create --name "Audit hub" --scope scans:read,findings:read
# Omit --scope only when this key must also trigger scans:
apex service-key create --name "Audit hub"
# Optional machine-readable output:
apex service-key create --name "Audit hub" --scope scans:read,findings:read --json
```

Apex CLI 0.1.16 and later automatically uses your company when only one is available. If you belong to multiple companies, it asks you to choose. Use `--company <id-or-handle>` to skip that prompt, or when a non-interactive command cannot prompt. Copy the secret into your secret manager when it is created. It cannot be retrieved later.

When `--scope` is omitted, the key gets all three scopes: `scans:create`, `scans:read`, and `findings:read`. List metadata or revoke a key without exposing its secret:

```javascript theme={null}
apex service-key list
apex service-key revoke <key-id>
```

## § 04 Trigger a scan

Send a unique, stable `Idempotency-Key` for each intended scan. Reuse that same value when retrying the same request.

Apex reuses the active workspace already linked to the repository. If more than one workspace matches, include its `workspaceId` in the body. The service API never creates or rewrites workspaces.

```javascript theme={null}
curl --request POST https://ai.cantina.xyz/api/apex/v1/scans \
  --header "Authorization: Bearer $APEX_SERVICE_KEY" \
  --header "Idempotency-Key: 8c8d9e5d-4fa6-4b65-bd42-14ddb5874c83" \
  --header "Content-Type: application/json" \
  --data '{
    "repoUrl": "https://github.com/acme/payments",
    "commit": "0123456789abcdef0123456789abcdef01234567",
    "paths": ["src", "packages/auth"]
  }'
```

> **Paths are focus hints**
> The optional `paths` array prioritizes those files in Apex prompts, but it is not a hard repository boundary. The scan may inspect or report code outside those paths. Omit it if you do not need focus hints; version one does not yet provide strict path isolation.

A successful request returns HTTP 202:

```javascript theme={null}
{
  "scanId": "3e559b86-f524-4b27-a175-fb4944c53f1b",
  "status": "queued",
  "statusUrl": "/api/apex/v1/scans/3e559b86-f524-4b27-a175-fb4944c53f1b",
  "findingsUrl": "/api/apex/v1/scans/3e559b86-f524-4b27-a175-fb4944c53f1b/findings"
}
```

## § 05 Poll scan status

```javascript theme={null}
curl --header "Authorization: Bearer $APEX_SERVICE_KEY" \
  https://ai.cantina.xyz/api/apex/v1/scans/<scan-id>
```

1. **Start** - Treat the HTTP 202 response as queued and retain its scanId.
2. **Poll** - Use bounded exponential backoff while status is queued or running.
3. **Stop** - Stop polling on completed, failed, or cancelled.
4. **Collect** - Fetch findings after the scan reaches completed.

## § 06 Fetch findings

```javascript theme={null}
curl --header "Authorization: Bearer $APEX_SERVICE_KEY" \
  https://ai.cantina.xyz/api/apex/v1/scans/<scan-id>/findings
```

The response is a GitLab SAST report. Each vulnerability includes the persisted Apex finding ID, title, description, severity, and available file and line location. IDs remain stable when you fetch the same scan again, so downstream systems can deduplicate safely.

Findings retrieval also works for scans started in the Apex web app, so an integration can begin with this endpoint before automating scan creation.

> **Findings access includes drafts**
> A key with `findings:read` can retrieve unpublished draft findings for scans in its organization so an external hub can perform triage. Treat the service key as a privileged credential and do not expose its findings payload to users who cannot review drafts in Apex.

The first request after a scan completes durably synchronizes the terminal finding set. If that sync is unavailable or has more pages, Apex returns `503` with `Retry-After`. Retry the same GET; after readiness is persisted, later requests serve the cached report without depending on Kernel.

## § 07 Errors and retries

| Code | Meaning                                                                                   |
| ---- | ----------------------------------------------------------------------------------------- |
| 400  | Invalid repository URL, commit SHA, path hint, or request body                            |
| 401  | Missing, malformed, expired, or revoked service key                                       |
| 403  | The key lacks the required scope                                                          |
| 404  | The scan does not exist in the key's organization                                         |
| 409  | Idempotency conflict, repository workspace mismatch, active scan, or a non-completed scan |
| 429  | Rate limit reached; respect Retry-After                                                   |
| 500  | Internal persistence or lookup failure; retry with backoff                                |
| 502  | Transient provider or Kernel failure; retry with the identical request when appropriate   |
| 503  | Scan finalization or first terminal findings sync is incomplete; respect Retry-After      |
| 504  | Kernel scan start timed out; retry the identical body with the same Idempotency-Key       |

> **Retry safely**
> GET requests are safe to retry. After a transport error, timeout, or `5xx`, retry POST only with the original body and the original `Idempotency-Key`. Idempotency is organization-scoped, so replay remains safe if the service key is rotated between attempts. A definitive `4xx` response is retained: after correcting its precondition, submit it as a new intended scan with a new `Idempotency-Key`. Never log the Authorization or X-API-Key header.

## § 08 Claude and Codex prompts

These prompts work in Claude Code or Codex. The first keeps key creation in your own terminal; the others ask the agent to use the service API for the headless runtime rather than trying to run MCP inside a serverless function.

* Give me the exact Apex CLI command I should run in my own terminal to create a service key named Audit hub. Do not run it for me or ask me to paste the secret into this chat.
* Using APEX\_SERVICE\_KEY from the environment, write a serverless TypeScript adapter that starts an Apex scan for this repository and commit. Send a stable Idempotency-Key, poll until terminal, and return the GitLab SAST findings.
* Add Apex to our audit hub. Call POST /api/apex/v1/scans, poll GET `/api/apex/v1/scans/{scanId}` with bounded backoff, then fetch /findings. Never log the bearer token and retry only safe requests.
* Given an Apex scanId for a scan started in the web app, fetch its GitLab SAST findings with APEX\_SERVICE\_KEY, preserve the raw response, and import each vulnerability once by stable ID. Do not trigger another scan or log the credential.
* Diagnose this Apex API response without printing secrets. Explain whether it is a transport/5xx retry that must preserve the original Idempotency-Key, or a definitive 4xx that must be corrected and submitted as a new intended scan with a new key.
