Let your users bring their own AI.You never hold the key.
The handoff
Standard OAuth 2.1. No webhooks, no polling. The redirect brings the result back.
You are on connect.drawee.dev
{ access_token, refresh_token }
- 1Your UI, your brand. One button.
- 2A plain form on our origin that names your app. Never an iframe.
- 3Back with a code your backend swaps for a token. That token is the user.
On the wirethe three requests, verbatim
Connect sends the browser to our origin
GET https://connect.drawee.dev/oauth2/authorize
?client_id=appfoo
&redirect_uri=https://appfoo.com/drawee/callback
&scope=inference:openai offline_access
&state=<csrf>We redirect back to your callback
GET https://appfoo.com/drawee/callback?code=abc&state=<csrf>Your backend exchanges the code
POST https://connect.drawee.dev/oauth2/token
grant_type=authorization_code&code=abc
&client_id=appfoo&client_secret=drawee_cs_…{ access_token, refresh_token, expires_in }
The code
Two calls. The gateway speaks OpenAI's API, so the official SDK works unchanged.
bun add draweeConnect
import { Drawee } from "drawee";
const drawee = new Drawee({
clientId: process.env.DRAWEE_CLIENT_ID!,
clientSecret: process.env.DRAWEE_CLIENT_SECRET,
redirectUri: "https://appfoo.com/drawee/callback",
});
// Your "Connect OpenAI" button
const { url, state, codeVerifier } = await drawee.authorize();
await session.set({ state, codeVerifier });
redirect(url);Send the browser to url. No proxy, no iframe: the origin change is how your user verifies who is asking.
Infer
import OpenAI from "openai";
const client = new OpenAI(drawee.openai(tokens.accessToken));
const res = await client.chat.completions.create({
model: "gpt-4o-mini",
messages: [{ role: "user", content: "Say hello in five words." }],
});Key or subscription is their choice, ranked at consent. Request bodies are forwarded verbatim.
Bring your own subscription
A ChatGPT subscription serves the same inference:openai scope as an API key. Your user ranks them; the ladder falls through in that order, and your code never notices.
Each user signs in with their own ChatGPT account and spends their own included usage. One person, one subscription, never pooled.
OpenAI
inference:openai- 1ActiveChatGPTSubscriptionPreferredPersonal ChatGPTIncluded in what you already pay···9c3f2afalls through to
- 2ActiveOpenAIAPI keyWork keyBilled to you per request···71b4d8
- What your user pays
- Nothing extra. It is the subscription they already have.
- What you pay
- $2.00 per subscription-served user, per month
You never hold the key
Every credential is sealed under one AWS KMS root. The key sits with the user, not the tenant: one person's credential, reachable by every app they allow.
Your user can revoke you at connect.drawee.dev without going through your app. That is what makes “you keep control of your key” true.
AWS KMS CMK one key for the platform
└─ user KEK one per end-user, wrapped by the CMK
└─ conn DEK one per connection, wrapped by that user's KEK
└─ the credential itself (AES-256-GCM)Integrate for free. Pay when you go live.
Sandbox is free and unmetered. The bill starts with the first user who connects through a live project. Idle projects cost nothing.
Per project, per month
| Connected users | Price |
|---|---|
| 1–100 | $99.00a month |
| 101–500 | $0.75each |
| 501–1,500 | $0.60each |
| 1,501–5,000 | $0.4286each |
| 5,001–20,000 | $0.30each |
| 20,001 and up | $0.20each |
Per project, per month. Rates are marginal.
A connected user is one distinct end-user with a successful request that month. Rates are marginal. A user served by their own subscription adds $2.00.
Add-ons
| Add-on | Price |
|---|---|
| SSO | $149.00a month |
| SCIM | $99.00a month |
Self-serve. No enterprise tier, no sales call.
Integrating costs nothing. Find out in an afternoon.
bun add drawee