Integrations & API

Integration API.

Submit requests, stream progress, respond to approvals, and retrieve artifacts from any system. A versioned REST API at /api/v1/integration.

Overview

The Integration API is generic by design — any system that can make HTTP requests (and optionally receive webhooks) can submit and manage Speakeasy requests. All endpoints are under /api/v1/integration and require authentication.

Authentication & Scopes

Authenticate with an API key (created in the Speakeasy Settings UI) or a session JWT:

Authorization: Bearer sk_live_...
# or
X-API-Key: sk_live_...

Each API key carries one or more scopes, enforced on every route:

  • requests:read - read status, detail, runs, messages, SSE stream
  • requests:write - submit requests and send actions
  • webhooks:manage - manage webhooks
  • artifacts:read - list and download artifacts and attachments

Scopes gate API-key callers; logged-in users are governed by their role instead. Key management (/api/settings/api-keys) requires an admin session user — API keys cannot create or revoke keys.

Submitting Requests

POST /api/v1/integration/requests
Content-Type: application/json

{
  "subject": "Field not visible on layout",
  "description": "Custom_Field__c on Account is not showing...",
  "organizationId": "<org-id>",        // or "organizationName"
  "severity": "medium",
  "externalId": "your-ref-123",
  "callbackUrl": "https://you.example.com/hook",
  "autoProcess": true
}

Accepts application/json or multipart/form-data (attachments field, up to 10 files, 25MB each; some executable extensions are blocked). Provide organizationId for deterministic routing — an ambiguous organizationName returns 400 with a candidates array, and an unknown org returns 404.

A successful submit returns 201:

{
  "requestId": "665a...",
  "requestNumber": "REQ-2026-0042",
  "status": "pending_review",
  "queued": true,
  "links": { "self": "...", "status": "...", "stream": "...", "actions": "..." }
}

Reading Requests

  • GET /requests - list (filters: status, externalId, page, limit [max 100])
  • GET /requests/:id - full detail (interpretation, findings, resolution, approval items, runs)
  • GET /requests/:id/status - lightweight payload for polling
  • GET /requests/:id/runs - agent runs with findings, artifacts, cost, timing
  • GET /requests/:id/messages - the conversation thread

Actions

All interactions go through one endpoint, discriminated by type:

POST /api/v1/integration/requests/:id/actions

{ "type": "respond", "response": "Yes, proceed" }
{ "type": "approve", "items": [{ "index": 0, "approved": true }] }
{ "type": "approve" }                       // approve all
{ "type": "reject", "reason": "Not needed" }
{ "type": "validation_decision", "decision": "accept" }
{ "type": "cancel" }                        // sets status to "canceled"
{ "type": "process", "note": "optional" }

Approving (when at least one item is approved) transitions the request to approved and queues deployment.

Webhooks

Register HTTP endpoints to receive events (request.created, request.status_changed, request.paused, request.approval_needed, request.completed, request.failed, request.artifact_created, and opt-in request.step_completed).

Each delivery is signed and includes an enriched data payload:

X-Speakeasy-Signature: sha256=<hex>
X-Speakeasy-Event: request.status_changed
X-Speakeasy-Delivery-Id: <uuid>

Verify with HMAC-SHA256(secret, raw_body). Delivery is 3 attempts (backoff 2s then 4s), 15s timeout each, auto-disabled after 10 consecutive failures. Manage via POST/GET/PATCH/DELETE /webhooks and POST /webhooks/:id/test.

SSE Streaming

GET /api/v1/integration/requests/:id/stream

Server-Sent Events with types connected, status, step, error, validation_window, and a heartbeat comment every 30 seconds. Each event carries an incrementing id. Server-side replay via Last-Event-ID is not implemented — on reconnect, re-fetch current state via the status endpoint.

Ingest Endpoints

Two additional submission paths exist with a different schema:

  • POST /api/ingest/api - programmatic submit (API key or session). Uses body (required) rather than description; does not accept callbackUrl, metadata, externalId, or attachments. Use /api/v1/integration/requests when you need those.
  • POST /api/ingest/email - the inbound email path, authenticated by the email provider's signature (not an API key). For the email provider, not general integration.

Known Limitations

Current, intentional gaps — stated plainly:

  • Per-request callbackUrl deliveries are unsigned. Registered webhooks are HMAC-signed; the per-request callback path is not. Treat callback payloads as unauthenticated.
  • No rate limiting. Callers should self-throttle.
  • No externalId deduplication. Submitting the same externalId twice creates two requests; enforce idempotency on your side if needed.

For the MCP server surface (used by agent platforms like Basil), and for tracing into GitHub and Railway, see Connected Platforms.