Skip to content

Connectors

A Sprite that needs to talk to GitHub, Anthropic, OpenAI, TypeSafeAI, OpenRouter, Meta, an S3 bucket, or any other HTTP API runs into the same problem: where does the credential live? Pasting a token into the Sprite’s environment works, but every Sprite that needs that token now holds a copy of a long-lived secret. Rotating it means touching every Sprite. Auditing access means reading process environments. Revoking it for one Sprite means revoking it for all of them.

Connectors solve this by storing the credential once, in your organization, and routing API calls through the Sprites gateway. Sprites never see the token. You decide which Sprites can use a connector and which provider endpoints they can reach.

A connector has three pieces:

  1. A credential — an OAuth token, your own API key, S3 access keys, or a managed key that Sprites provisions for you. Stored encrypted in your organization’s database. The token itself is never returned by the API or shown again in the dashboard.
  2. An access policy — rules that decide which of your Sprites may use the connector, and which provider paths they may reach. Deny-by-default: a connector with no policy refuses every Sprite.
  3. A gateway endpointhttps://api.sprites.dev/v1/gateway/<provider>/<connection_id>/<path>. A Sprite calls this URL; Sprites authenticates the call using the requesting Sprite’s identity, checks the policy, and forwards to the provider with the stored credential attached.

The Sprite never holds the provider token. It only knows the connector ID and the gateway URL.

ProviderCredential styleNotes
GitHubOAuthYou approve access on GitHub. Default scopes are repo and read:org; add more later from the connector’s Scopes editor. The token reaches every repository you can see.
GitHub AppGitHub AppInstall the Sprites GitHub App on your account or organization, choose the repositories it may reach, then authorize. Sprites reach only those repositories, with the App’s fine-grained permissions. There are no scopes. Tokens rotate every eight hours.
Slack (User)OAuthSprites act as you in your workspace. Default scopes cover posting, reading channels and history, users, team info, and search.
Slack (Bot)OAuthSprites act as a bot user. Same default scopes as Slack (User) minus search:read.
OpenRouterAPI key (BYOK) or managedBring your own OpenRouter key, or enable the managed connector and pay with prepaid credits. See Managed OpenRouter.
AnthropicAPI key (BYOK)Calls to /v1/messages and the rest of the Anthropic API. The gateway forwards your anthropic-version and anthropic-beta headers.
MetaAPI key (BYOK)Muse Spark models through the Meta Model API. Forwards the OpenAI-compatible /v1/chat/completions and /v1/responses routes, the Anthropic-compatible /v1/messages route, and /v1/models; every other Meta path is rejected with 403.
OpenAIAPI key (BYOK)GPT models through the OpenAI API. Forwards /v1/responses, /v1/chat/completions, /v1/completions, /v1/embeddings, and /v1/models. The OpenAI SDKs work unchanged with OPENAI_BASE_URL set to the connector URL; the Codex CLI needs a model_provider entry. Files, fine-tuning, batches, and organization endpoints are rejected with 403.
TypeSafeAIAPI key (BYOK)Jev, a decision model that answers typed questions (yes/no, one of N, score) with calibrated probabilities. Forwards POST /v1/systemone and GET /v1/models only. The Python and JavaScript SDKs and the TypeSafeAI agent skill work unchanged with TYPESAFE_BASE_URL set to the connector URL.
DiscourseForum-issued user API keyYou approve access on the forum itself. The connector only ever gets your own forum permissions.
S3-compatible object storeAccess key ID + secretAWS S3, Cloudflare R2, Backblaze B2, MinIO, and other S3-compatible services. Requests are signed with SigV4.
Fly.io MachinesFly.io tokenA Custom API preset for api.machines.dev. The dashboard mints a read-only or read-write token scoped to your organization.
Custom APIToken + base URLWraps any token-authenticated HTTP API. You choose where the token goes.

Connector management lives in the Fly.io dashboard. Open your organization, go to Sprites, then the Connectors tab. Connections are grouped into Managed by Sprites (keys Sprites provisions for you) and Your connections (everything you added yourself). An Available services strip below lists managed connectors you haven’t enabled yet.

Click Add connector to pick a provider.

The Add connector page in the Sprites dashboard, showing a grid of providers: Fly.io Machines, Slack, GitHub, Discourse, OpenRouter, Anthropic, S3-compatible Object Store, and Custom API

What happens next depends on the provider:

  • GitHub — click Continue with GitHub. You’re sent through GitHub’s OAuth consent screen, then returned to your connectors list.
  • GitHub App — first click Install on GitHub and choose the repositories the App may reach, then click Continue with GitHub to authorize. If the App is not installed on any account you can reach, the connector is refused with a link to the install page. The connector page lists each installation with its repositories and permissions. Change the selection on GitHub and it applies at once; click Reconnect to refresh the list.
  • Slack (User) or Slack (Bot) — click Continue with Slack and approve the requested scopes in your workspace. Pick User when the Sprite should post and read as you, and Bot when it should show up as its own bot user. You can connect both.
  • OpenRouter — either Enable OpenRouter for the managed connector, or Use your own key instead and paste an OpenRouter API key.
  • Anthropic, Meta, OpenAI, TypeSafeAI, and other API-key providers — paste the key. It’s validated against the provider before it’s saved, encrypted at rest, and never shown again.
  • Discourse — enter the forum URL and choose Read-only or Read & write. Approve access on the forum in a new tab, then paste the code the forum displays back into the form.
  • S3-compatible object store — enter the bucket, endpoint URL, region, access key ID, and secret access key. Click Test connection (a HEAD request against the bucket) before you can save.
  • Fly.io Machines — choose a read-only or read-write token scope and click Generate token. The token is created under your account and named Sprite connector (…) so you can find it later under Tokens.
  • Custom API — fill in the base URL, the access token, and the authentication method. Then set a test URL and click Test connection. The Add connector button stays disabled until the test passes.

For Custom API connectors, the Authentication method decides where the token goes:

MethodWhat the gateway sends
HeaderAuthorization: <prefix> <token>. The prefix defaults to Bearer; leave it blank to send the token verbatim.
URL pathA path template such as /bot{token} inserted between the base URL and the request path. {token} is replaced at request time.
Query paramThe token appended as a query parameter (default name api_key).
Custom headerThe token as the value of a header you name (default X-Api-Key).

A few guardrails apply to Custom API connectors. The base URL must resolve to a public address, so you can’t point a connector at a private network, a loopback address, or the Sprites API itself. Header names starting with fly-, x-fly-, sprites-, x-sprite, or x-ui-ex- are reserved and rejected. Requests that trip these checks fail with a 403 blocked: … error.

You can also give a Custom API connector an Icon (JPG, PNG, SVG, or WebP, up to 512 KB) by choosing a file or pasting an image into the form. It shows up in the connectors list and on the detail page.

The optional Description on a Custom API connector isn’t just a label. It’s surfaced to coding agents through the gateway’s list endpoint, so a line like “Use /v1/chat/completions for chat” tells an agent how to use the API.

Newly created connectors show up in the list immediately. Until you grant access to at least one Sprite, the connector is dormant. It exists, but no Sprite can use it.

Click any connector to open its detail page. This is where you control which Sprites can use it and what they can do with it.

The Access Configuration card has three controls:

  • Name Prefix — only Sprites whose name starts with the value you set (for example, prod- matches prod-1 and prod-api).
  • Sprite Labels — one label per line. Only Sprites that carry all the labels you list get access. Labels are set on the Sprite, not here.
  • Allow all sprites — every Sprite in the organization. Checking it disables the other two fields, and the dashboard flags it as a broad permission.

You can combine name prefix and labels. Both must match. Allow-all overrides the others. Changes aren’t applied until you click Save.

The Authorized Sprites list below updates live as you edit the rules (it’s titled Matching Sprites while you have unsaved changes), so you can see exactly which Sprites will gain access before you save. Each Sprite in the list has a Test button that fires a real request from that Sprite through the gateway and reports success or failure with the round-trip time. It’s the fastest way to confirm the policy works end to end.

For OAuth connectors, the Scopes section shows what the provider granted. Click Add scope to pick more from the provider’s catalog, then Re-authorize to go back through the provider’s consent screen with the expanded set.

Other actions on the detail page:

  • Edit API key rotates a BYOK key in place. The new key is validated before it replaces the old one.
  • Edit connection and Clone connection on Custom API and object-store connectors. Cloning prefills a new form with everything except the secrets.
  • Reauthorize on Discourse connectors. Forum-issued keys expire after a period of disuse (180 days by default), and the gateway returns 403 once that happens.
  • Enable for this org and Disable for this org on platform-provided connectors, which Sprites operates for every organization. Disabling one cuts off your Sprites without deleting anything.
  • Remove connection asks you to type the connector’s name. Deleting a connector destroys the credential and immediately cuts off every Sprite using it.

Once the policy grants access, a Sprite calls the connector by hitting the gateway URL:

https://api.sprites.dev/v1/gateway/<provider>/<connection_id>/<path>

No Authorization header. The gateway identifies the calling Sprite from Fly.io’s request signature. Whatever path and query string you append after the connector ID is forwarded to the provider with the stored credential attached. GET, HEAD, POST, PUT, PATCH, and DELETE are supported.

For example, if you set up a GitHub connector and granted access to Sprites with the github label:

Terminal window
curl -X POST "https://api.sprites.dev/v1/gateway/github/conn_gh789abc012/repos/acme/website/issues" \
-H "Content-Type: application/json" \
-d '{"title": "Flaky test in CI", "body": "Opened from a Sprite"}'

An Anthropic connector works the same way. The gateway forwards anthropic-version and anthropic-beta, so the Anthropic SDK pointed at the gateway URL works as it does against the API directly:

Terminal window
curl -X POST "https://api.sprites.dev/v1/gateway/anthropic/<connection_id>/v1/messages" \
-H "Content-Type: application/json" \
-H "anthropic-version: 2023-06-01" \
-d '{"model": "claude-opus-5", "max_tokens": 1024, "messages": [{"role": "user", "content": "Hello!"}]}'

A Meta connector accepts the same request shapes as the APIs it emulates: OpenAI-style /v1/chat/completions and /v1/responses, Anthropic-style /v1/messages, plus /v1/models. Point the OpenAI or Anthropic SDK’s base URL at https://api.sprites.dev/v1/gateway/meta/<connection_id>/v1 with any placeholder API key; the gateway swaps in the stored one. Streaming and tool calls pass through unchanged. Any other Meta path is rejected with 403 before the request leaves the gateway.

Terminal window
curl -X POST "https://api.sprites.dev/v1/gateway/meta/<connection_id>/v1/chat/completions" \
-H "Content-Type: application/json" \
-d '{"model": "muse-spark-1.3", "messages": [{"role": "user", "content": "Hello!"}]}'

Model availability is set per Meta developer team, so GET /v1/models through the connector is the authoritative list.

An OpenAI connector forwards the inference surface of the OpenAI API: /v1/responses (including retrieving, cancelling, and deleting a response and listing its input items), /v1/chat/completions, /v1/completions, /v1/embeddings, and /v1/models. The gateway swaps the caller’s Authorization header for the stored key and forwards OpenAI-Organization, OpenAI-Project, and OpenAI-Beta when the SDK sets them. Streaming and tool calls pass through unchanged, and so do OpenAI’s error bodies and x-ratelimit-* headers. Files, fine-tuning, batches, vector stores, and organization endpoints are rejected with 403 before the request leaves the gateway.

Terminal window
curl -X POST "https://api.sprites.dev/v1/gateway/openai/<connection_id>/v1/responses" \
-H "Content-Type: application/json" \
-d '{"model": "gpt-5-mini", "input": "Hello!"}'

The official SDKs read OPENAI_BASE_URL, so no code changes are needed (the Codex CLI does not; see Running Codex CLI through an OpenAI connector). Set it to the connector URL, ending in /v1, and give OPENAI_API_KEY any non-empty placeholder; the gateway supplies the real key:

Terminal window
export OPENAI_BASE_URL="https://api.sprites.dev/v1/gateway/openai/<connection_id>/v1"
export OPENAI_API_KEY="sprites"
from openai import OpenAI
client = OpenAI() # picks up OPENAI_BASE_URL and OPENAI_API_KEY
response = client.responses.create(model="gpt-5-mini", input="Hello!")
print(response.output_text)

Model availability depends on the OpenAI project the key belongs to, so GET /v1/models through the connector is the authoritative list.

A TypeSafeAI connector forwards Jev’s two routes: POST /v1/systemone for typed decisions and GET /v1/models for discovery. Jev is not a chat model. A request sends a state and a map of typed questions, and the answer carries a probability and confidence per question, plus token usage. There is no text generation and no streaming. 422, 429 and 529 responses and the retry-after header pass through, so the SDKs’ retry logic works as it does against the API directly. Any other path or method is rejected with 403.

Terminal window
curl -X POST "https://api.sprites.dev/v1/gateway/typesafe/<connection_id>/v1/systemone" \
-H "Content-Type: application/json" \
-d '{
"model": "jev-latest",
"state": "Hi, my Stripe connection has failed for 3 days. I am losing sales. Please help ASAP.",
"questions": {
"is_urgent": {"type": "noul", "instructions": "Does this message express urgency?"},
"department": {"type": "choice", "instructions": "Which team should handle this?",
"criteria": {"billing": "Payments and refunds", "technical": "Bugs and integrations", "sales": "Pricing and upgrades"}},
"frustration": {"type": "score", "instructions": "How frustrated is the customer?",
"criteria": ["Calm", "Frustrated but civil", "Very angry"]}
}
}'

Both SDKs read TYPESAFE_BASE_URL. Set it to the connector URL, without a trailing /v1, and give TYPESAFE_API_KEY any non-empty placeholder; the gateway supplies the real key:

Terminal window
export TYPESAFE_BASE_URL="https://api.sprites.dev/v1/gateway/typesafe/<connection_id>"
export TYPESAFE_API_KEY="sprites"
from typesafe_sdk import Noul, TypeSafeClient
client = TypeSafeClient() # picks up TYPESAFE_BASE_URL and TYPESAFE_API_KEY
response = client.system_one(
state="Hi, my Stripe connection has failed for 3 days. Please help ASAP.",
questions={"is_urgent": Noul(instructions="Does this message express urgency?")},
)
print(response.answers["is_urgent"].noul) # e.g. 0.95
import { noul, TypeSafeClient } from "@typesafe-ai/sdk";
const client = new TypeSafeClient(); // picks up TYPESAFE_BASE_URL and TYPESAFE_API_KEY
const response = await client.systemOne({
state: "Hi, my Stripe connection has failed for 3 days. Please help ASAP.",
questions: { is_urgent: noul({ instructions: "Does this message express urgency?" }) },
});
console.log(response.answers.is_urgent.noul); // e.g. 0.95

GET /v1/models through the connector lists the aliases your account can use, such as jev-latest. The response’s model field reports the versioned ID that answered.

The API Usage card on each connector’s detail page shows a ready-to-run example for that provider, so you don’t need to construct the URL by hand.

A few things to know about the gateway:

  • Server-sent events stream through. When a provider answers with text/event-stream, the gateway relays events as they arrive, so "stream": true on OpenAI-compatible and Anthropic requests works as it does against the provider directly. Other responses are read in full before they’re returned.
  • Request headers are mostly not forwarded. The gateway sets Content-Type and its own User-Agent. Only provider-specific headers the connector opts into (such as Anthropic’s version headers, or the standard S3 request headers) pass through.
  • Rate-limit headers do come back. GitHub, OpenRouter, Anthropic, Meta, OpenAI, TypeSafeAI, and Slack connectors forward their *-ratelimit-* and retry-after response headers. Slack connectors also return x-slack-req-id, x-oauth-scopes, and x-accepted-oauth-scopes, which is handy for diagnosing a missing scope.
  • Object-store requests keep their raw body. Uploads through an S3 connector can be up to 64 MB per request. Range, the If-* conditional headers, Content-MD5, Content-Type, and any x-amz-* request header pass through, so ranged downloads and object metadata work as they do against the bucket directly.
  • OAuth tokens refresh themselves. When a provider token is within five minutes of expiring, the gateway refreshes it before forwarding the request. You don’t need to handle refresh in the Sprite.
  • Upstream timeout is 120 seconds.

The access policy can also restrict which provider paths a Sprite can reach through the connector. This is useful when a connector has more permission than you want any single Sprite to use. A GitHub connector that can open issues and pull requests probably shouldn’t be able to call admin endpoints.

Patterns are exact paths or trailing-wildcard prefixes:

  • /repos/acme/website/issues — exactly that path.
  • /repos/* — anything starting with /repos/.
  • /* — everything (use sparingly).

Slack’s API uses dotted method names rather than nested paths, so a Slack pattern looks like /chat.postMessage for one method or /chat.* for the whole chat family.

There’s no mid-string globbing or regular expressions. Two lists work together:

  • Allowed endpoints — if set, only matching paths are allowed. An empty list means no restriction.
  • Blocked endpoints — matching paths are rejected. Block rules are checked before allow rules.

Sprites can provision an OpenRouter key for your organization so you don’t need an OpenRouter account at all. Click Enable OpenRouter from the Connectors tab (or the Available services strip) and the connector appears under Managed by Sprites, available to every Sprite in the organization once you set an access policy.

Managed OpenRouter is prepaid. A newly provisioned key starts with a spending limit of zero, so the first step after enabling it is to buy credits:

  • Click Buy credits on the connector card or detail page. Pick $10, $25, $50, $100, or enter a custom amount.
  • Purchases are charged to your organization’s default card on file. If there isn’t one, the dialog sends you to Billing first.
  • Credits are applied automatically once payment confirms, which can take a few minutes. The Credit purchases list on the detail page shows each purchase and its state.

The detail page shows Available credits and a Recent spend band with totals for the last 24 hours, 7 days, and 30 days. Spend figures come from gateway telemetry and are close to, but not the same as, the authoritative balance OpenRouter enforces.

When credits run out, requests fail with 403 and a message telling you where to top up. A 402 means the remaining balance can’t cover a single request’s max_tokens. Either lower max_tokens or buy more credits.

A managed connector otherwise behaves exactly like one you set up yourself: you still set an access policy, and the per-Sprite Test button still works. If you also have a bring-your-own-key OpenRouter connector, the managed one is created disabled so the two don’t compete. You can switch between them from the detail page.

Every Sprite ships with the sprite-api-gateway skill pre-installed for Claude Code, Cursor, Codex, and Gemini. When a coding agent running inside a Sprite needs to talk to an external API, the skill kicks in automatically, so you don’t have to teach it any of the URLs above.

Ask in plain language:

“Comment ‘tests are green, ready to merge’ on GitHub PR #42 in acme/website.”

“Open a GitHub issue in my repo titled ‘flaky test’.”

“Summarize this file with Claude through our Anthropic connector.”

“Write a haiku with GPT through our OpenAI connector.”

“Use the TypeSafe skill to decide whether each support ticket is urgent, through our TypeSafeAI connector.”

The agent discovers what’s available by calling the gateway list endpoint from inside the Sprite:

Terminal window
curl -s https://api.sprites.dev/v1/gateway/list

The response has two arrays. connections lists the connectors this Sprite is authorized to use, each with its gateway_base_url (already including the connection ID), a display_name, a description, a usage_snippet showing an example call, the granted scopes, and a manage_url for the dashboard. Custom API connectors also include their base_api_url and auth_method. available lists providers that could be connected but aren’t yet, with their default_scopes.

The agent picks the right connector, builds the call against the gateway, and never sees a raw token.

If an OAuth connector exists but is missing scopes the agent needs, the connection’s request_scopes_url points you at the re-authorization flow. A Sprite can also start that flow itself with GET /v1/gateway/authorize?provider=github&add_scopes=…, which returns an authorize_url for you to open. If no connector exists for the provider, the agent will ask you to add one from the dashboard.

The practical effect: once an organization admin has set up a GitHub connector and granted access to the right Sprites, anyone using a coding agent inside one of those Sprites can use the integration in natural language, with no API knowledge required.

Running Codex CLI through an OpenAI connector

Section titled “Running Codex CLI through an OpenAI connector”

The Codex CLI is itself an OpenAI client, so it can run inside a Sprite against an OpenAI connector with no OpenAI key in the Sprite. Current Codex releases ignore OPENAI_BASE_URL for the built-in openai provider, so declare the connector as its own model provider in ~/.codex/config.toml:

model_provider = "sprites"
[model_providers.sprites]
name = "OpenAI via Sprites"
base_url = "https://api.sprites.dev/v1/gateway/openai/<connection_id>/v1"
env_key = "OPENAI_API_KEY"
wire_api = "responses"

Then give Codex a placeholder key and run it as usual:

Terminal window
export OPENAI_API_KEY="sprites" # any non-empty value; the gateway supplies the real key
codex "Explain what this repository does"

The same settings work as one-off flags. Codex requires the name field, so pass all four:

Terminal window
codex exec -c model_provider=sprites \
-c 'model_providers.sprites.name="OpenAI via Sprites"' \
-c 'model_providers.sprites.base_url="https://api.sprites.dev/v1/gateway/openai/<connection_id>/v1"' \
-c 'model_providers.sprites.env_key="OPENAI_API_KEY"' \
-c 'model_providers.sprites.wire_api="responses"' \
"Explain what this repository does"

Codex uses the Responses API, which the connector forwards. Sign-in with ChatGPT is not available through a connector; it needs an API key on the OpenAI side.

Using the TypeSafeAI agent skill through a connector

Section titled “Using the TypeSafeAI agent skill through a connector”

TypeSafeAI ships an agent skill that teaches Claude Code, Codex and other agents how to design questions and thresholds. It runs test queries with the SDK, so it needs the same two variables. Install it in the Sprite and export the connector URL:

Terminal window
npx skills add typesafe-ai/skills --skill typesafe-ai
export TYPESAFE_BASE_URL="https://api.sprites.dev/v1/gateway/typesafe/<connection_id>"
export TYPESAFE_API_KEY="sprites"

Then ask the agent, for example, “Using the TypeSafe skill, run some experiments against TYPESAFE_API_KEY.” The key never leaves your organization; the Sprite only holds the placeholder.

403 no access policy configured — connection denies all sprites by default The connector has no access policy. Open the connector and grant access via labels, name prefix, or allow-all.

403 sprite is missing required labels: … or 403 sprite name must start with '…' The connector has a policy, but the calling Sprite doesn’t match it. The message names the missing labels or the required prefix.

403 endpoint is blocked by policy or 403 endpoint is not in allowed list The path matches a blocked endpoint, or an allowed-endpoints list is set and this path isn’t on it. Check both lists via the API.

401 could not verify sprite identity The request didn’t arrive with valid Fly.io identity headers. Gateway calls must originate from inside a running Sprite, not from your laptop or CI.

404 no <provider> connection configured for this organization The connection ID in the URL doesn’t exist in this Sprite’s organization, or has been deleted.

502 failed to reach <Provider> API The gateway couldn’t connect to the provider. Retry, and check the provider’s status page if it persists.

403 with "credits_exhausted" or 402 with "credits_insufficient" from an OpenRouter connector Your managed OpenRouter credits are used up, or too low for this request. Buy more credits from the connector page.

403 blocked: base URL resolves to a non-public address or 403 blocked: connector may not set the reserved header … A Custom API connector points at a private or loopback address, or uses a reserved header name. See the guardrails under Setting up a connector.

OAuth callback returns failed to exchange authorization code The authorization code was already used or has expired. Restart the connection from the dashboard.

Everything in the dashboard is also available as a REST API. Useful when you want to provision connectors as part of an org-setup script, or rotate them programmatically. These endpoints take a Sprites API token; only the gateway itself uses Sprite identity.

Terminal window
curl "https://api.sprites.dev/v1/oauth/providers" \
-H "Authorization: Bearer $SPRITES_TOKEN"

Returns each provider available to your organization with its display name, credential style, default scopes, and scope catalog.

Terminal window
curl -X GET "https://api.sprites.dev/v1/oauth/github/authorize?scopes=repo,read:org" \
-H "Authorization: Bearer $SPRITES_TOKEN"

Returns an authorize_url and a state. Send the user to the URL; on consent, GitHub redirects back to the Sprites callback and the connector is created. The same flow works with slack and slack_bot in place of github. Pass add_scopes instead of scopes to merge new scopes into an existing connection’s grant. For github_app, omit scopes: a GitHub App has none, and the user must have installed the App before the callback succeeds.

Terminal window
curl -X POST "https://api.sprites.dev/v1/oauth/connections/api_key" \
-H "Authorization: Bearer $SPRITES_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "provider": "anthropic", "api_key": "sk-ant-...", "access_policy": { "allow_all": true } }'

Works for openrouter, anthropic, ollama, meta, openai, and typesafe. The key is validated against the provider before it’s stored. Rotate it later with PUT /v1/oauth/connections/<id>/api_key.

Terminal window
curl -X POST "https://api.sprites.dev/v1/oauth/connections/custom_api" \
-H "Authorization: Bearer $SPRITES_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Telegram",
"base_api_url": "https://api.telegram.org",
"access_token": "123456:ABC...",
"auth_method": "url_path",
"auth_url_path_template": "/bot{token}",
"test_url": "/getMe",
"access_policy": { "sprite_labels": ["bots"] }
}'

name, base_api_url, access_token, and test_url are required. auth_method is one of header (default, with optional auth_header_prefix), url_path (with auth_url_path_template), query_param (with auth_query_param_name), or custom_header (with auth_custom_header_name). POST /v1/oauth/connections/custom_api/test takes the same body and verifies the credential without saving.

Terminal window
curl -X POST "https://api.sprites.dev/v1/oauth/connections/object_store" \
-H "Authorization: Bearer $SPRITES_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "production-assets",
"bucket": "assets",
"endpoint_url": "https://<account>.r2.cloudflarestorage.com",
"region": "auto",
"access_key_id": "...",
"secret_access_key": "...",
"access_policy": { "name_prefix": "prod-" }
}'
Terminal window
curl -X POST "https://api.sprites.dev/v1/oauth/connections/provision" \
-H "Authorization: Bearer $SPRITES_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "provider": "openrouter" }'

Credits are purchased from the dashboard. GET /v1/oauth/connections/<id>/balance returns the current limit, usage, and remaining balance, and GET /v1/oauth/connections/<id>/usage returns daily, weekly, and monthly spend with a per-model breakdown. Both require an unrestricted API token; a scoped token gets a 403.

Terminal window
curl -X PUT "https://api.sprites.dev/v1/oauth/connections/<id>" \
-H "Authorization: Bearer $SPRITES_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "access_policy": { "sprite_labels": ["github"], "allowed_endpoints": ["/repos/*"] } }'

The policy is replaced wholesale, so include every field you want to keep.

Terminal window
curl -X POST "https://api.sprites.dev/v1/oauth/connections/<id>/test_gateway" \
-H "Authorization: Bearer $SPRITES_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "sprite_name": "prod-1" }'

Runs a real request from the named Sprite through the gateway and returns status, message, and latency_ms. This is what the Test button on the detail page calls.

OperationEndpoint
ListGET /v1/oauth/connections (each entry includes sprite_count)
Get oneGET /v1/oauth/connections/:id
DeleteDELETE /v1/oauth/connections/:id

Deleting a connector immediately revokes all Sprite access to it. The encrypted credential is destroyed and cannot be recovered. If the connector was OAuth, the user must re-authorize from the dashboard to recreate it.

For the full request and response schemas, see the API reference.