Services API
Services represent external platforms and APIs that your agents can access. STACK maintains a catalog of 60+ pre-configured services (Slack, GitHub, Google, Stripe, etc.) and supports custom service connections for any API not in the catalog. Service credentials are encrypted with AWS KMS at rest and only decrypted in-memory on retrieval.
All endpoints require authentication via Authorization: Bearer sk_live_.... Write operations (connect, disconnect, grant, configure, verify, proxy-toggle) require at least standard role.
List Available Services
GET /v1/services
Retrieve the full catalog of available services that can be connected. Each service includes its provider key, display name, and whether it supports OAuth or credential-based connection.
curl https://api.getstack.run/v1/services \
-H "Authorization: Bearer sk_live_your_key"List Connected Services
GET /v1/services/connected
Retrieve all services currently connected to your operator account. Includes connection status, verification state, and who connected the service. Credentials are never returned in list responses — use the Credentials API to retrieve them.
curl https://api.getstack.run/v1/services/connected \
-H "Authorization: Bearer sk_live_your_key"Connect a Catalog Service
POST /v1/services/connect
Connect a service from the catalog. Provide the service ID, desired scopes, and optionally an OAuth token (for OAuth services) or redirect URI.
curl -X POST https://api.getstack.run/v1/services/connect \
-H "Authorization: Bearer sk_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"service_id": "svc_slack",
"scopes": ["channels:read", "chat:write"],
"redirect_uri": "https://getstack.run/api/oauth/callback"
}'ConnectServiceInput Fields
- service_id (string, required) — the service ID from the catalog
- scopes (string[], required) — at least one scope must be specified
- redirect_uri (string, optional) — OAuth redirect URI
The request body can also include oauth_token (for completing an OAuth flow) and member_id (to attribute the connection to a specific member).
Returns 201 with the created connection object.
Connect a Custom Service
POST /v1/services/custom
Connect a custom service that is not in the STACK catalog. Supports both single-field credentials (API key string) and multi-field credentials (key-value pairs). Custom services are private to your account and do not appear in the public catalog.
Single-field Credential
curl -X POST https://api.getstack.run/v1/services/custom \
-H "Authorization: Bearer sk_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Internal CRM",
"description": "Company internal CRM API",
"credential": "crm_key_abc123",
"scopes": ["read", "write"]
}'Multi-field Credential
curl -X POST https://api.getstack.run/v1/services/custom \
-H "Authorization: Bearer sk_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"name": "SFTP Server",
"description": "Production SFTP for invoice uploads",
"credential": {
"host": "sftp.example.com",
"username": "stack-agent",
"password": "s3cur3p4ss",
"port": "22"
}
}'ConnectCustomServiceInput Fields
- name (string, required) — display name, 1-100 chars
- description (string, optional) — human-readable description, max 500 chars
- credential (string | Record<string, string>, optional) — single API key string or key-value pairs. Optional to allow enabling a service without connecting.
- scopes (string[], optional) — free-form scopes for documentation purposes
- template (string, optional) — if provided, validates credential fields against the named template
- oauth_auth_url (string, optional) — custom OAuth authorization URL
- oauth_token_url (string, optional) — custom OAuth token URL
If providing oauth_auth_url, you must also provide oauth_token_url (and vice versa). They must be provided together.
Custom services are stored with a custom_ prefix on the provider field (e.g., custom_internal_crm). Multi-field credentials are stored as an encrypted JSON string and returned as a credentials object on retrieval.
Returns 201 with the created connection object.
Disconnect a Service
DELETE /v1/services/:id/disconnect
Disconnect a service and permanently delete its stored credentials. This also cascades: any agents with grants to this connection have their active passports revoked.
curl -X DELETE https://api.getstack.run/v1/services/conn_abc123/disconnect \
-H "Authorization: Bearer sk_live_your_key"Disconnecting a service immediately invalidates all credential access and revokes active passports for any agents that had grants to this connection. Any agent workflows that depend on this service connection will fail until reconnected.
Verify a Connection
POST /v1/services/:id/verify
Test that a service connection is working by making a health check request against the service API. For services with credential templates, STACK uses the template's verification URL. For OAuth services, STACK calls a known "me" endpoint (e.g., Slack's auth.test, GitHub's /user).
curl -X POST https://api.getstack.run/v1/services/conn_abc123/verify \
-H "Authorization: Bearer sk_live_your_key"Returns the verification result with status healthy or an error. Updates the verification_status and verified_at columns on the connection.
{
"status": "healthy",
"verified_at": "2026-04-15T10:35:00Z"
}Grant Agent Access to a Service
POST /v1/services/grant
Grant an agent access to a specific service connection with scoped permissions. The scopes must be a subset of the connection's scopes.
curl -X POST https://api.getstack.run/v1/services/grant \
-H "Authorization: Bearer sk_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"agent_id": "agt_abc123",
"service_connection_id": "conn_abc123",
"scopes": ["channels:read", "chat:write"]
}'GrantAgentAccessInput Fields
- agent_id (string, required) — the agent to grant access to
- service_connection_id (string, required) — the service connection ID
- scopes (string[], required) — at least one scope, must be a subset of the connection scopes
Returns 201 with the created grant object.
Revoke Agent Access
DELETE /v1/services/agents/:agentId/revoke
Revoke all service grants for an agent. This also cascades: active passports for the agent are revoked since the agent lost its service grants.
curl -X DELETE https://api.getstack.run/v1/services/agents/agt_abc123/revoke \
-H "Authorization: Bearer sk_live_your_key"{
"success": true
}Get Agent Permissions
GET /v1/agents/:agentId/permissions
Retrieve all service grants for a specific agent, showing which connections and scopes the agent has access to.
curl https://api.getstack.run/v1/agents/agt_abc123/permissions \
-H "Authorization: Bearer sk_live_your_key"Toggle Proxy Access
POST /v1/services/:id/proxy-toggle
Enable or disable proxy access for a specific service connection. When proxy is enabled, agents can use the Proxy API to make authenticated requests through STACK without accessing the raw credential.
curl -X POST https://api.getstack.run/v1/services/conn_abc123/proxy-toggle \
-H "Authorization: Bearer sk_live_your_key" \
-H "Content-Type: application/json" \
-d '{ "proxy_enabled": true }'Request Body
- proxy_enabled (boolean, required) — true to enable proxy, false to disable
Configure Service Mode
POST /v1/services/configure
Configure how a service connection is shared within the organization. The mode controls whether a single connection is shared across all members or each member has their own.
curl -X POST https://api.getstack.run/v1/services/configure \
-H "Authorization: Bearer sk_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"service_id": "svc_slack",
"provider": "slack",
"mode": "per_member"
}'Request Body
- service_id (string, required) — the service ID
- provider (string, required) — the provider slug
- mode (enum, required) — "shared" | "per_member"
List Service Configurations
GET /v1/services/configurations
Retrieve all service configurations for your organization, showing the sharing mode for each configured service.
curl https://api.getstack.run/v1/services/configurations \
-H "Authorization: Bearer sk_live_your_key"Delete Service Configuration
DELETE /v1/services/configurations/:provider
Remove the service configuration for a provider, reverting it to default behavior.
curl -X DELETE https://api.getstack.run/v1/services/configurations/slack \
-H "Authorization: Bearer sk_live_your_key"List Credential Templates
GET /v1/services/templates
Retrieve all available credential templates. Templates define the fields required to connect a service, along with help URLs and verification endpoint configurations. Currently 19 templates are available covering popular APIs.
curl https://api.getstack.run/v1/services/templates \
-H "Authorization: Bearer sk_live_your_key"{
"templates": [
{
"provider": "openai",
"name": "OpenAI",
"fields": [
{
"key": "api_key",
"label": "API Key",
"type": "password",
"required": true,
"placeholder": "sk-proj-..."
}
],
"help_url": "https://platform.openai.com/api-keys",
"verification_url": "https://api.openai.com/v1/models",
"verification_headers": {
"Authorization": "Bearer {{api_key}}"
}
}
]
}Template field values use {{field_key}} interpolation in verification headers and URLs. When verifying a connection, STACK substitutes the actual credential values and checks for a 2xx response.
Tier Limits
The number of service connections depends on your plan:
- Free — 3 services
- Developer ($9.99/mo) — 25 services
- Studio ($99/mo) — Unlimited services
- Enterprise — Unlimited services
Endpoint Summary
GET /v1/services — list catalog services
GET /v1/services/connected — list your connections
GET /v1/services/templates — list credential templates
GET /v1/services/configurations — list service configurations
POST /v1/services/connect — connect a catalog service
POST /v1/services/custom — connect a custom service
POST /v1/services/configure — set service sharing mode
POST /v1/services/grant — grant agent access
POST /v1/services/:id/verify — verify a connection
POST /v1/services/:id/proxy-toggle — toggle proxy access
DELETE /v1/services/:id/disconnect — disconnect a service
DELETE /v1/services/agents/:agentId/revoke — revoke agent grants
DELETE /v1/services/configurations/:provider — delete configuration
GET /v1/agents/:agentId/permissions — get agent service permissions