WorkOS Docs Homepage
Pipes
API referenceDashboardSign In
Getting StartedOverviewOverviewCustom providersCustom providersOrganization-scoped providersOrganization-scoped providersAPI key providersAPI key providersRelayRelayProvidersProviders
API Reference
API Reference
Events
Events
Integrations
Integrations
Migrate to WorkOS
Migrate to WorkOS
SDKs
SDKs

Relay

Call third-party APIs on behalf of your users without handling their provider credentials.

On this page

  • Overview
  • How it works
  • Before you begin
  • Making requests
    • Request headers
    • URL routing
    • Path routing
  • Examples
    • Query Linear
    • Post a Slack message
  • Organization scoping
  • Handling authorization
  • Responses
  • Limits and behavior
  • Supported providers
  • Error reference

Overview

Relay calls third-party APIs on your users’ behalf without exposing their credentials to your application. Send the request to WorkOS, and relay attaches the user’s credential server-side and streams the provider’s response back.

Relay is in early access. Contact support via email or Slack to request access for your environment.

Relay is a forward HTTP proxy built for AI agents and other untrusted runtimes. With access tokens, your infrastructure fetches a provider access token and calls the provider directly, so the token exists inside the calling environment, where it can be copied, logged, or leaked. With relay, the provider credential never leaves WorkOS: the agent authenticates with your WorkOS API key and names the user it acts for.

Relay removes provider credentials from the calling environment, not the WorkOS API key. That key authenticates every WorkOS API call for the environment, so treat it as a secret even in a sandbox: inject it at request time rather than baking it into agent-visible code or prompts, and rotate it from the API Keys section of the dashboard if a runtime is compromised.

How it works

Every proxied request follows the same lifecycle:

  1. Authenticate. Your WorkOS API key is verified and determines the environment. The key is stripped from the request and is never sent upstream.
  2. Resolve the user. The X-Relay-User header identifies the user the request acts on behalf of, scoped by X-Relay-Organization when the connection belongs to an organization.
  3. Look up the connected account. WorkOS finds the user’s Pipes connection for the provider you named. If the user hasn’t connected, or needs to reconnect, relay returns a 402 response.
  4. Resolve the credential. WorkOS retrieves and refreshes OAuth access tokens, retrieves stored API keys, or mints access tokens from stored client credentials, depending on how the account is connected.
  5. Inject and forward. Relay control headers, cookies, and forwarding metadata are stripped, the provider credential is injected into the provider’s configured request header, and the request is forwarded over HTTPS.
  6. Stream the response. The provider’s status, headers, and body are streamed back verbatim, with an added X-Relay-Upstream-Status header.

Before you begin

Relay builds on your existing Pipes setup. You need:

  • A WorkOS API key for the environment, from the API Keys section of the WorkOS Dashboard.
  • The target provider enabled for your environment, configured in the Pipes section of the dashboard or through the data integration API.
  • A connected account for the user, created through the provider’s OAuth flow, by entering an API key, or with the client credentials endpoint.

Relay uses the connected account’s authentication method – OAuth, API key, or client credentials – without changing the relay request format. The provider’s Relay configuration determines which methods it accepts and how the credential is presented upstream.

Making requests

The base URL is https://api.workos.com/relay, and any HTTP method is accepted. To convert a direct provider call into a proxied one:

  1. Keep the method, body, and content headers as they are.
  2. Send the request to the relay base URL, and move the original URL into the X-Relay-URL header.
  3. Authenticate with your WorkOS API key in Authorization.
  4. Name the user in X-Relay-User, adding X-Relay-Organization for organization-scoped connections.

Request headers

Header Required Description
Authorization Yes Bearer followed by your WorkOS API key. Determines the environment. Never forwarded to the provider.
X-Relay-User Yes The ID of the user the request acts on behalf of, for example user_01EHZ…. Must belong to the API key’s environment.
X-Relay-Organization Conditional The organization the connection was authorized under, for example org_01KV9…. Required when the connection is organization-scoped, and must be omitted when it isn’t.
X-Relay-URL URL routing only The full upstream URL, including path and query string. Must use HTTPS.
X-Relay-Provider No The provider slug to relay to, for example github. Optional with URL routing, where the provider is otherwise resolved from the host.

All other request headers, including Content-Type, Accept, and provider-specific headers, are forwarded unchanged. See limits and behavior for the headers that are stripped.

URL routing

Put the complete upstream URL in X-Relay-URL. The provider is resolved from the URL’s host, so your code keeps working with the provider’s real URLs. Name the provider explicitly with X-Relay-Provider when the host is ambiguous, or when you would rather not depend on host inference.

curl --request GET https://api.workos.com/relay \
--header "Authorization: Bearer sk_example_123456789" \
--header "X-Relay-URL: https://api.github.com/user/repos?per_page=5" \
--header "X-Relay-User: user_01EHZNVPK3SFK441A1RGBFSHRT" \
--header "X-Relay-Organization: org_01EHZNVPK3SFK441A1RGBFSHRT"

Path routing

Alternatively, prefix the provider’s API path with the relay base URL and the provider’s slug. The slug in the path selects the provider, and the path and query string are appended to the provider’s default API host, so /relay/github/user proxies to https://api.github.com/user.

curl --request GET "https://api.workos.com/relay/github/user/repos?per_page=5" \
--header "Authorization: Bearer sk_example_123456789" \
--header "X-Relay-User: user_01EHZNVPK3SFK441A1RGBFSHRT" \
--header "X-Relay-Organization: org_01EHZNVPK3SFK441A1RGBFSHRT"

URL routing is the better default: it can reach any of a provider’s allowed hosts rather than only the default one, and it keeps the provider’s own URLs intact in your code and logs.

Examples

Query Linear

curl --request POST https://api.workos.com/relay \
--header "Authorization: Bearer sk_example_123456789" \
--header "X-Relay-URL: https://api.linear.app/graphql" \
--header "X-Relay-User: user_01EHZNVPK3SFK441A1RGBFSHRT" \
--header "X-Relay-Organization: org_01EHZNVPK3SFK441A1RGBFSHRT" \
--header "Content-Type: application/json" \
--data '{"query": "{ viewer { id name email } }"}'

Post a Slack message

curl --request POST https://api.workos.com/relay \
--header "Authorization: Bearer sk_example_123456789" \
--header "X-Relay-URL: https://slack.com/api/chat.postMessage" \
--header "X-Relay-User: user_01EHZNVPK3SFK441A1RGBFSHRT" \
--header "X-Relay-Organization: org_01EHZNVPK3SFK441A1RGBFSHRT" \
--header "Content-Type: application/json" \
--data '{"channel": "C01XXXXXXXX", "text": "Hello from Pipes Relay"}'

Organization scoping

Pipes connections are either scoped to an organization or user-only, and the connection lookup requires an exact match on that scope:

  • If the user authorized the provider under an organization, requests must include X-Relay-Organization with that organization’s ID.
  • If the user authorized the provider without an organization, the header must be omitted.

A scope mismatch in either direction returns the same 402 relay_authorization_required response as a user who never connected at all. If a connected user keeps getting a 402, check that the X-Relay-Organization header matches the organization on their connected account before asking them to re-authorize.

Handling authorization

When the user has no usable connection for the provider – they never connected, their OAuth grant was revoked, or their token can no longer be refreshed – the response is 402 Payment Required:

{
"code": "relay_authorization_required",
"connection": "github",
"message": "User has not authorized provider \"github\"",
"authorization_url": "https://github.com/login/oauth/authorize?client_id=..."
}

For OAuth connections, surface the authorization_url, let the user complete the provider’s authorization flow, then retry the original request.

authorization_url is null for API key and client credentials connections. Collect or rotate those credentials through the Pipes widget, the upsert API key endpoint, or the client credentials endpoint, then retry. It can also be null when a provider’s OAuth configuration is incomplete.

Authorization-required responses use 402, not 401 or 403, so they can’t be confused with a WorkOS authentication failure (401) or a provider-returned 401 or 403 passed through from upstream.

Responses

On success you receive the provider’s status code, headers, and body exactly as the provider sent them, streamed as they arrive. Provider errors are passed through untouched, so a GitHub 404 comes back as a 404 with GitHub’s own error body.

Every proxied response carries an X-Relay-Upstream-Status header with the provider’s status code. Its presence means the request reached the provider, so you can distinguish an upstream 404 from a relay 404 such as an unknown provider.

Limits and behavior

Behavior Detail
Request body Forwarded byte-for-byte, up to 5 MB. GET and HEAD requests send no body.
Upstream timeout 30 seconds. A provider that doesn’t respond in time yields 502 relay_upstream_error.
HTTPS only X-Relay-URL must use HTTPS. Credentials are never injected into a plaintext request.
Host allowlist Requests can only target a supported provider’s allowed hosts. Anything else is rejected before the request is sent.
Redirects Not followed. Redirect responses are returned as-is.
Stripped request headers Hop-by-hop headers such as Connection and Transfer-Encoding, Cookie, forwarding metadata such as X-Forwarded-*, Via, and X-Real-IP, your Authorization header, and anything prefixed X-Relay- or X-WorkOS-.
Stripped response headers Hop-by-hop headers and Set-Cookie. Compressed bodies are decoded in transit, so Content-Encoding and Content-Length may be removed.

Supported providers

Relay supports the active providers below. With path routing, the request goes to the provider’s base API host. With URL routing, any listed host is allowed. The provider must also be enabled for your environment.

The Authentication column shows the methods explicitly configured for each provider. Relay can also mint tokens for eligible client credentials connections; contact support to confirm provider eligibility during early access.

Provider Slug Authentication Allowed hosts
Acuity Scheduling acuity-scheduling OAuth acuityscheduling.com
Addepar addepar OAuth api.addepar.com
Adobe adobe OAuth ims-na1.adobelogin.com
Aimfox aimfox OAuth, API key api.aimfox.com
Aircall aircall OAuth api.aircall.io
Airtable airtable OAuth, API key api.airtable.com
Anthropic anthropic API key api.anthropic.com
Apaleo apaleo OAuth api.apaleo.com
Apollo.io apollo-oauth OAuth, API key app.apollo.io
Asana asana OAuth, API key app.asana.com
Ashby ashby API key api.ashbyhq.com
Atlassian atlassian OAuth, API key api.atlassian.com
Attio attio OAuth, API key api.attio.com
Autodesk autodesk OAuth developer.api.autodesk.com
BambooHR bamboohr OAuth api.bamboohr.com
beehiiv beehiiv API key api.beehiiv.com
Bing Webmasters bing-webmasters OAuth www.bing.com
BitBucket bitbucket OAuth api.bitbucket.org
Bitly bitly OAuth, API key api-ssl.bitly.com
BoldSign boldsign OAuth, API key api.boldsign.com
Box box OAuth api.box.com, upload.box.com
Braintree braintree OAuth api.braintreegateway.com
Brandfetch brandfetch API key api.brandfetch.io
Brex brex OAuth, API key platform.brexapis.com
Buffer buffer OAuth api.buffer.com
Cal.com cal-dot-com OAuth, API key api.cal.com
Calendly calendly OAuth, API key api.calendly.com
Candis candis OAuth api.candis.io
Canva canva OAuth api.canva.com
CircleCI circleci API key circleci.com
Clerk clerk API key api.clerk.com
CleverReach cleverreach OAuth rest.cleverreach.com
ClickUp clickup OAuth, API key api.clickup.com
Close close OAuth, API key api.close.com
Cloudbeds cloudbeds OAuth, API key api.cloudbeds.com, hotels.cloudbeds.com
Cloudflare cloudflare OAuth, API key api.cloudflare.com
Cohere cohere API key api.cohere.com
Confluence confluence OAuth api.atlassian.com
Constant Contact constant-contact OAuth api.cc.email
Conta Azul conta-azul OAuth api-v2.contaazul.com
Contentful contentful OAuth api.contentful.com
Copper copper OAuth api.copper.com
Crowdin crowdin OAuth api.crowdin.com
Datadog datadog OAuth api.datadoghq.com
DATEV datev OAuth api.datev.de
Deel deel OAuth, API key api.letsdeel.com
Deepgram deepgram API key api.deepgram.com
DeepSeek deepseek API key api.deepseek.com
Dialpad dialpad OAuth, API key dialpad.com
DigitalOcean digitalocean OAuth, API key api.digitalocean.com
Digits digits OAuth connect.digits.com
Discord discord OAuth, API key discord.com
Dovetail dovetail API key dovetail.com
DrChrono drchrono OAuth app.drchrono.com
Dropbox dropbox OAuth api.dropboxapi.com, content.dropboxapi.com
Dropbox Sign dropbox-sign OAuth, API key api.hellosign.com
ElevenLabs elevenlabs API key api.elevenlabs.io
Employment Hero employment-hero OAuth api.employmenthero.com
Envoy envoy OAuth, API key api.envoy.com
Eventbrite eventbrite OAuth, API key www.eventbriteapi.com
Exa exa API key api.exa.ai
Factorial factorial OAuth, API key api.factorialhr.com
Fathom fathom OAuth, API key api.fathom.ai
Figma figma OAuth, API key api.figma.com
Firecrawl firecrawl API key api.firecrawl.dev
Fireworks fireworks API key api.fireworks.ai
Fly.io fly-io OAuth, API key api.machines.dev
Fortnox fortnox OAuth api.fortnox.se
Frame.io frame-io OAuth, API key api.frame.io
Frame.io V4 frame-io-v4 OAuth, API key api.frame.io
FreeAgent freeagent OAuth api.freeagent.com
FreshBooks freshbooks OAuth api.freshbooks.com
Front front OAuth, API key api2.frontapp.com
G2 g2 API key data.g2.com
Gamma gamma OAuth, API key public-api.gamma.app
GitHub github OAuth, API key api.github.com
GitLab gitlab OAuth, API key gitlab.com
Gmail gmail OAuth gmail.googleapis.com
Google google OAuth www.googleapis.com
Google BigQuery bigquery OAuth bigquery.googleapis.com
Google Calendar google-calendar OAuth www.googleapis.com
Google Docs google-docs OAuth www.googleapis.com
Google Drive google-drive OAuth www.googleapis.com
Google Gemini google-gemini OAuth, API key generativelanguage.googleapis.com
Google Meet google-meet OAuth www.googleapis.com
Google Sheets google-sheets OAuth www.googleapis.com
Google Slides google-slides OAuth www.googleapis.com
Grain grain OAuth, API key api.grain.com
Granola granola API key public-api.granola.ai
Greenhouse greenhouse API key harvest.greenhouse.io
Greenhouse (Ingestion API) greenhouse-ingestion OAuth api.greenhouse.io
Gusto gusto OAuth api.gusto.com
Harvest harvest OAuth, API key api.harvestapp.com
Health Gorilla health-gorilla OAuth api.healthgorilla.com
Help Scout helpscout OAuth api.helpscout.net
HeyGen heygen OAuth, API key api2.heygen.com
HOVER hover OAuth api.hover.to
HubSpot hubspot OAuth, API key api.hubapi.com
Hugging Face hugging-face OAuth huggingface.co
incident.io incident-io API key api.incident.io
Intercom intercom OAuth, API key api.intercom.io
Intralinks intralinks OAuth api.intralinks.com
Jira jira OAuth api.atlassian.com
Jobber jobber OAuth api.getjobber.com
Kakao kakao OAuth, API key kapi.kakao.com
Keap keap OAuth api.infusionsoft.com
Kernel kernel API key api.onkernel.com
Klaviyo klaviyo OAuth, API key a.klaviyo.com
LaunchDarkly launchdarkly OAuth app.launchdarkly.com
Lever lever OAuth, API key api.lever.co
Linear linear OAuth, API key api.linear.app
LinkedIn linkedin OAuth api.linkedin.com
Local Falcon local-falcon API key api.localfalcon.com
Lokalise lokalise OAuth, API key api.lokalise.com
Luma luma API key public-api.luma.com
Mailgun mailgun API key api.eu.mailgun.net, api.mailgun.net
Manufact manufact API key cloud.manufact.com
Mem0 mem0 API key api.mem0.ai
Mercury mercury OAuth, API key api.mercury.com
Microsoft microsoft OAuth graph.microsoft.com
Microsoft OneDrive microsoft-onedrive OAuth graph.microsoft.com
Microsoft OneNote microsoft-onenote OAuth graph.microsoft.com
Microsoft Outlook microsoft-outlook OAuth graph.microsoft.com
Microsoft Outlook Calendar microsoft-outlook-calendar OAuth graph.microsoft.com
Microsoft SharePoint microsoft-sharepoint OAuth graph.microsoft.com
Microsoft Teams microsoft-teams OAuth graph.microsoft.com
Microsoft To-Do microsoft-todo OAuth graph.microsoft.com
Miro miro OAuth, API key api.miro.com, miro.com
Mollie mollie OAuth, API key api.mollie.com
Monday.com monday OAuth, API key api.monday.com
Motive motive OAuth, API key api.gomotive.com, api.keeptruckin.com
Mural mural OAuth app.mural.co
Neon neon OAuth, API key console.neon.tech
Netlify netlify OAuth, API key api.netlify.com
ngrok ngrok API key api.ngrok.com
Notion notion OAuth, API key api.notion.com
npm npm API key registry.npmjs.org
OpenAI openai API key api.openai.com
OpenRouter openrouter API key openrouter.ai
Orb orb API key api.withorb.com
Outreach outreach OAuth api.outreach.io
PagerDuty pagerduty OAuth, API key api.pagerduty.com
PandaDoc pandadoc OAuth, API key api.pandadoc.com
Pardot pardot OAuth pi.demo.pardot.com, pi.pardot.com
PayPal paypal OAuth api-m.paypal.com
Pennylane pennylane OAuth, API key app.pennylane.com
Perk perk OAuth, API key api.travelperk.com
Perplexity perplexity API key api.perplexity.ai
Plain plain API key core-api.uk.plain.com
PlanetScale planetscale OAuth api.planetscale.com
Podium podium OAuth api.podium.com
Postman postman API key api.getpostman.com
PreciseFP precisefp OAuth app.precisefp.com
Procore procore OAuth api.procore.com
Productboard productboard OAuth, API key api.productboard.com
QuickBooks quickbooks OAuth quickbooks.api.intuit.com
QuickBooks Time tsheetsteam OAuth rest.tsheets.com
Railway railway API key backboard.railway.com
Ramp ramp OAuth api.ramp.com
Reapit reapit OAuth platform.reapit.cloud
Reddit reddit OAuth oauth.reddit.com
Render render API key api.render.com
Replicate replicate API key api.replicate.com
Resend resend API key api.resend.com
RingCentral ring-central OAuth platform.ringcentral.com
Sage sage OAuth api.accounting.sage.com
Sage Intacct sage-intacct OAuth api.intacct.com
Salesloft salesloft OAuth, API key api.salesloft.com
Salesmsg salesmsg OAuth api.salesmessage.com
Segment segment API key api.segmentapis.com
Sellsy sellsy OAuth api.sellsy.com
SendGrid sendgrid API key api.sendgrid.com
Sentry sentry OAuth, API key sentry.io
Serval serval OAuth public.api.serval.com
ServiceM8 servicem8 OAuth, API key api.servicem8.com
signNow signnow OAuth api.signnow.com
Slack slack OAuth slack.com
Slack User slack-user OAuth slack.com
Socket socket API key api.socket.dev
Spotify spotify OAuth api.spotify.com
Stripe stripe OAuth, API key api.stripe.com
Stripe Connect stripe-connect OAuth, API key api.stripe.com
SurveyMonkey survey-monkey OAuth, API key api.surveymonkey.com
Teamleader Focus teamleader OAuth api.focus.teamleader.eu
Ticket Tailor ticket-tailor API key api.tickettailor.com
TickTick ticktick OAuth api.ticktick.com
TikTok tiktok OAuth open.tiktokapis.com
Timely timely OAuth api.timelyapp.com
Todoist todoist OAuth api.todoist.com
Tremendous tremendous OAuth, API key api.tremendous.com
TriNet HR Platform (Zenefits) zenefits OAuth api.trinet.com, api.zenefits.com
Typeform typeform OAuth, API key api.typeform.com
VideoAsk videoask OAuth api.videoask.com
Wave Accounting wave-accounting OAuth, API key gql.waveapps.com
Wealthbox wealthbox OAuth, API key api.crmworkspace.com
Webex webex OAuth, API key webexapis.com
Webflow webflow OAuth, API key api.webflow.com
WHOOP whoop OAuth api.prod.whoop.com
Wix wix OAuth www.wixapis.com
WorkOS workos API key api.workos.com
X.com x-com OAuth, API key api.twitter.com, api.x.com
xAI xai API key api.x.ai
Xero xero OAuth api.xero.com
Zapier zapier OAuth api.zapier.com
Zendesk Sell zendesk-sell OAuth, API key api.getbase.com
Zeplin zeplin OAuth api.zeplin.dev
Zoom zoom OAuth api.zoom.us

Error reference

Errors generated by relay are JSON objects with code and message fields. Provider errors are passed through unchanged, so check for X-Relay-Upstream-Status to tell the two apart.

Status Code Meaning
401  –  Missing or invalid WorkOS API key.
400 relay_missing_url URL routing was used but the X-Relay-URL header is absent.
400 relay_invalid_url X-Relay-URL isn’t a valid URL or doesn’t use HTTPS, or the resolved target host isn’t one of the provider’s allowed hosts.
400 relay_user_required The X-Relay-User header is absent.
400 relay_user_not_found No user with that ID exists in the API key’s environment.
400 relay_provider_conflict The path slug and the X-Relay-Provider header name different providers.
400 relay_credential_invalid The stored credential can’t be presented to the provider – it needs to be replaced.
402 relay_authorization_required The user has no usable connection for this provider, or the organization scope doesn’t match. The authorization_url may be null.
404 relay_provider_not_found The slug or the X-Relay-URL host doesn’t match a supported provider, or the provider isn’t enabled in this environment.
404 relay_provider_not_configured The provider has no relay configuration for the way this account is connected.
404  –  A generic 404 with no code field means relay isn’t enabled for this environment.
502 relay_credential_error The user’s credential couldn’t be resolved, for a reason that re-authorization won’t fix.
502 relay_upstream_error The provider was unreachable or timed out.
Providers Explore the third-party providers available for Pipes integrations
Up next
© WorkOS, Inc.
FeaturesAuthKitSingle Sign-OnDirectory SyncAdmin PortalFine-Grained Authorization
DevelopersDocumentationChangelogAPI Status
ResourcesBlogPodcastPricingSecuritySupport
CompanyAboutCustomersCareersLegalPrivacy
© WorkOS, Inc.