Skip to content

Integrations API

Integrations come in two flavors: the GitHub App (which powers private-repo deploys, repo/branch listing, and push-to-deploy) and marketplace integrations (Sentry, Resend, Stripe, and more) that inject env vars into your projects. Credentials are encrypted at rest and never returned raw — reads surface only a masked hint.

Concept guide: Integrations overview.

All routes require authentication except the GitHub events webhook, which verifies an HMAC signature.


GET /v1/integrations/github/connection

Auth: any member. Response (IntegrationConnection): { connected, type, installationId, username }.

POST /v1/integrations/github/authorize

Saves a GitHub App installation_id for the org (the connect flow’s completion step).

Auth: member. Body (AuthorizeGithubInput): { installationId } (coerced positive int). Response: IntegrationConnection.

Terminal window
curl -X POST https://api.pandastack.io/v1/integrations/github/authorize \
-H "Authorization: Bearer $PANDASTACK_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "installationId": 12345678 }'

GET /v1/integrations/github/repositories

Repos accessible via the installation token.

Auth: any member. Response: GithubRepo[] — each { fullName ('owner/repo'), private, defaultBranch }.

GET /v1/integrations/github/branches

Auth: any member. Query: ?repo=owner/repo. Response: GithubBranch[] — each { name, commitSha }.

Terminal window
curl "https://api.pandastack.io/v1/integrations/github/branches?repo=acme/my-app" \
-H "Authorization: Bearer $PANDASTACK_TOKEN"

DELETE /v1/integrations/github/:installationId

Auth: member. Response: { removed: true }.


GET /v1/integrations/catalog

The marketplace catalog: categories, kinds, and entries.

Auth: any member. Response (IntegrationCatalog): { categories: string[], kinds: string[], entries: CatalogEntry[] }.

CatalogEntry:

FieldTypeNotes
idstring
namestring
categorystring
kindNative | External
statuslive | coming_soon
connectionTypeapi_key
provisionsbooleanOptional; whether connecting provisions a resource.
descriptionstring
colorstring
iconUrlstring | null
websitestring
envVarsstring[]Env vars this integration injects.
inputFieldsCatalogInputField[]Optional; each { key, label, placeholder?, type (text|password), required, hint? }.

GET /v1/integrations/statuses

All connected integration statuses (masked).

Auth: any member. Response (IntegrationStatuses): a record keyed by integration type, each value an IntegrationStatus.

GET /v1/integrations/:type/status

Auth: any member. Response (IntegrationStatus): { type, connected, maskedKey, metadata, connectedAt }.


POST /v1/integrations/:type/connect

Connect a third-party integration — the credential is validated then encrypted.

Auth: member. Body (ConnectIntegrationInput):

FieldTypeRequiredNotes
apiKeystringnoTrimmed. The provider credential.
metadatarecord<string,string>noExtra fields from the catalog inputFields.

Response: IntegrationStatus.

Terminal window
curl -X POST https://api.pandastack.io/v1/integrations/sentry/connect \
-H "Authorization: Bearer $PANDASTACK_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "apiKey": "sntrys_xxx", "metadata": { "org": "acme" } }'

DELETE /v1/integrations/:type/disconnect

Auth: member. Response: { removed: true }.

GET /v1/integrations/:type/projects

Projects linked to an integration.

Auth: any member. Response: LinkedProject[] — each { projectId, name, slug, envVars, redeployed }.

POST /v1/integrations/:type/link-projects

Links the integration to one or more projects — injects env vars and best-effort redeploys.

Auth: member. Body (LinkProjectsInput): { projectIds } — array of positive ints, min 1. Response (LinkProjectsResult): { linked: LinkedProject[] }.

Terminal window
curl -X POST https://api.pandastack.io/v1/integrations/sentry/link-projects \
-H "Authorization: Bearer $PANDASTACK_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "projectIds": [812, 900] }'

DELETE /v1/integrations/:type/unlink/:projectId

Auth: member. Response: { removed: true }.


POST /api/v1/webhook/github-events

Receives GitHub App events. It is not token-authenticated — it verifies the x-hub-signature-256 header (HMAC-SHA256, timing-safe compare over the raw body) and reads x-github-event. Configure this as your GitHub App webhook URL; do not call it yourself.

A recognized event (for example a push on a tracked branch) triggers a deploy of the matching project. It responds fast (200) and is not wrapped in the standard envelope:

{ "success": true }

An event that does not map to any action returns:

{ "success": true, "handled": false }