Predict.aiDocs
Ingestion

OAuth connectors

Connect providers like Stripe and X with a consent flow instead of pasted credentials.

Some providers are connected by authorizing an account rather than pasting keys. The flow is the standard browser dance: you request an authorization URL, the user consents in a popup, and the provider redirects back to the platform's callback.

Providers come in two kinds, and the callback behaves differently for each:

KindExampleAfter the user consents
eventX / TwitterThe event source and its poll job are created immediately; you get a source_id
sourceStripeOnly the tokens are stored; you get a token_ref to use in the connect flow

List providers

The catalog of registered providers and whether each has client credentials configured on this deployment:

curl "$API_BASE/v1/ingestion/oauth/providers" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Workspace-Id: $WORKSPACE_ID"
{
  "data": {
    "status": "ok",
    "providers": {
      "twitter": { "id": "twitter", "label": "X / Twitter", "kind": "event", "configured": true },
      "stripe": { "id": "stripe", "label": "Stripe", "kind": "source", "configured": true }
    }
  }
}

Start the flow

Request the provider's authorization URL, then open it in a popup. For event providers you can pass a stream name for the resulting event source:

curl -X POST "$API_BASE/v1/ingestion/oauth/twitter/start" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Workspace-Id: $WORKSPACE_ID" \
  -H "Content-Type: application/json" \
  -d '{ "stream": "x_mentions" }'
{
  "data": {
    "status": "ok",
    "authorize_url": "https://twitter.com/i/oauth2/authorize?response_type=code&client_id=…&state=…",
    "state": "9c2f6c1e40a94b3c…"
  }
}

Request body

FieldMeaning
stream optionalevent providers only: the stream name for the resulting event source.

The state (and a PKCE verifier, where the provider supports it) is held server-side and validated on the callback — you don't need to store it.

Errors

StatusWhyExample message
404Provider isn't registered"Unknown OAuth provider: notion"
400Provider registered but no client credentials on this deployment"Stripe OAuth isn't configured on this deployment. Set oauth.stripe.client_id/client_secret."

The callback

GET /v1/ingestion/oauth/{provider}/callback is the redirect target the provider calls — it's public (validated by state), meant for the browser, and returns an HTML page rather than JSON. The page posts a message to the window that opened the popup:

// event provider — the source already exists
{ "type": "oauth_done", "provider": "twitter", "source_id": "3f8a1c2e-…" }

// source provider — continue through connect with the token_ref
{ "type": "oauth_done", "provider": "stripe", "token_ref": "tok_9b41…" }

// failure
{ "type": "oauth_done", "provider": "stripe", "error": "access_denied" }

Listen for that oauth_done message in your app; don't call the callback URL yourself.

Using a token_ref

For source providers, feed the token_ref into the normal connect flow as OAuth credentials:

curl -X POST "$API_BASE/v1/ingestion/connect/inspect" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Workspace-Id: $WORKSPACE_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "connector_type": "stripe",
    "credentials": { "auth_type": "oauth", "token_ref": "tok_9b41…" }
  }'

Then continue with connect/create as usual. A token_ref only works in the workspace that authorized it — using it elsewhere fails with "This connected account isn't available in this workspace. Reconnect it." Tokens are stored encrypted and refreshed automatically; their lifecycle follows the source they're bound to.

On this page