Connect Links
Hosted OAuth flow that lets your end users connect their own Stripe, Mercado Pago, Shopify, and other provider accounts — without you building or maintaining a connection UI.
Connect Links
@codespar/sdkv0.3.0A Connect Link is a hosted page that runs the entire OAuth dance for an end user: provider consent, callback handling, token exchange, encrypted storage, and scope checks. Your agent sends the link, the user clicks, and on the next tool call CodeSpar uses the stored credentials automatically.
You never touch raw provider tokens. You never build a connection UI. You never write the refresh logic.
Connect Links are for end-user authentication — your customers connecting their own Stripe / Mercado Pago / Shopify accounts. For your credentials (the platform's own provider keys shared across all users), use Service Auth instead.
Lifecycle
A connection moves through a small state machine:
start authorize token exchange
┌────────┐ link ┌──────────┐ code ┌──────────────┐
│ CLIENT │ ───────▶│ HOSTED │ ──────▶│ CODESPAR │
│ │ │ PAGE │ │ VAULT │
└────────┘ └──────────┘ └──────────────┘
│ │
│ tools execute │
│ ◀────────────────────────────────────────┘
│ using stored credential| Status | Meaning |
|---|---|
pending | A Connect Link was issued. User has not authorized yet. |
connected | Token stored in vault, scoped to userId. Tools will run. |
expired | Refresh token is dead (user revoked on the provider side, or token TTL elapsed without activity). Re-issue a Connect Link. |
revoked | Your application called /v1/connections/:id/revoke. Stored credentials were deleted. |
Credentials are scoped to the userId you passed to codespar.create(). User A never reaches user B's Stripe account — tenant isolation is enforced in the vault, not at the application layer.
Two integration patterns
Pick the pattern that matches when the user connects.
Pattern 1 — in-chat
The user is already in a conversation with your agent. The agent tries a tool, CodeSpar notices no connection exists, and the tool result returns a Connect Link that the agent surfaces in the chat.
const session = await codespar.create("user_abc", {
servers: ["stripe"],
manageConnections: { waitForConnections: false },
});
const result = await session.execute("codespar_checkout", {
amount: 14900,
currency: "BRL",
});
if (result.error === "needs_connection") {
// result.data.connect_url is the hosted page
// Send it to the user in the conversation
await chat.send(`Connect your Stripe account to continue: ${result.data.connect_url}`);
}Use when: chat-first products where interrupting the flow for an onboarding page hurts conversion. WhatsApp commerce agents, embedded support assistants, in-app copilots.
Pattern 2 — manual (pre-onboarding)
You want users connected before they chat. Your onboarding screen or settings page calls session.authorize() and redirects to the Connect Link.
const session = await codespar.create("user_abc", {
servers: ["stripe"],
});
const { connected, redirectUrl } = await session.authorize("stripe");
if (!connected && redirectUrl) {
window.location.href = redirectUrl;
}After the user authorizes, your configured success redirect URL is called. On subsequent agent runs, any session created with the same userId picks up the stored credential automatically.
Use when: dashboards, settings pages, multi-tenant SaaS products where "connect your accounts" is part of onboarding.
session.authorize()
The SDK entry point for issuing a Connect Link.
const result = await session.authorize("stripe", {
redirectUrl: "https://app.example.com/onboarding/done",
scopes: ["read_write"], // override defaults
});Returns:
interface AuthResult {
connected: boolean; // true if already connected — skip redirect
redirectUrl?: string; // hosted Connect Link URL
error?: string; // if the server does not support this auth type
}If connected: true you can skip the redirect entirely — the stored credential is still valid.
Backend shape
The SDK wraps three HTTP endpoints. You can call them directly from any language.
| Method | Endpoint | Purpose |
|---|---|---|
POST | /v1/connections/start | Issue a Connect Link for a user + server |
GET | /v1/connections | List this user's connections and statuses |
POST | /v1/connections/:id/revoke | Delete the stored credential (end-user opt-out) |
POST /v1/connections/start
curl -X POST https://api.codespar.dev/v1/connections/start \
-H "Authorization: Bearer csk_live_..." \
-H "Content-Type: application/json" \
-d '{
"user_id": "user_abc",
"server_id": "stripe",
"redirect_url": "https://app.example.com/onboarding/done"
}'Response:
{
"link_token": "clt_abc123...",
"authorize_url": "https://codespar.dev/connect/stripe?token=clt_abc123",
"expires_at": "2026-04-17T16:00:00Z"
}The authorize_url is the Connect Link. link_token expires after 15 minutes; re-issue if the user takes longer.
GET /v1/connections
curl https://api.codespar.dev/v1/connections?user_id=user_abc \
-H "Authorization: Bearer csk_live_..."Response:
{
"data": [
{
"id": "conn_abc123",
"server_id": "stripe",
"user_id": "user_abc",
"auth_type": "oauth",
"status": "connected",
"display_name": "acme-store.myshopify.com",
"connected_at": "2026-04-17T15:30:00Z",
"expires_at": "2027-04-17T15:30:00Z"
}
]
}Customizing the hosted page
Connect Links inherit your org's branding. Configure once in Settings:
| Setting | Effect |
|---|---|
| Logo | Shown at the top of the hosted page |
| Accent color | Primary button and links |
| Custom domain | Serve from connect.yourdomain.com instead of codespar.dev/connect/* (requires CNAME + certificate) |
| Success redirect | Default URL after authorization if redirect_url is omitted |
| Legal footer | Privacy policy and ToS links shown beside provider consent |
The Connect Link page is static HTML + CSS — no third-party scripts, no analytics pixels. It's designed to pass enterprise security reviews on the first pass.
Troubleshooting
The user authorized but status is still pending. Wait up to 10 seconds — the callback is asynchronous. If it still hasn't flipped, check the triggers event stream: a failed token exchange fires connection.failed with an error_code explaining why (scope rejected, redirect URI mismatch, etc.).
"redirect_uri_mismatch" from the provider. Your provider's app config must whitelist https://codespar.dev/oauth/callback (or your custom domain's equivalent). See the provider page for the exact URI.
The Connect Link works in test but 404s in production. Live keys issue live Connect Links; test keys issue test Connect Links. You cannot hand a csk_test_-issued link to a user authenticating against a real Stripe account.
Expired token after months of inactivity. Providers revoke refresh tokens when a user hasn't used your app for a provider-defined period (Stripe: 13 months, Shopify: 24 hours of inactivity on some scopes). CodeSpar fires connection.expired via a trigger — re-issue a Connect Link when you receive it.
Next steps
Last updated on