Dravo uses your developer application for each platform. There are two setup stages: first configure the app in the platform's developer console, then store its OAuth client credentials in Dravo. Dravo owns the token exchange and token storage; the platform app, its review and its rate limits remain yours.
Before you start
You need:
- A Dravo account with dashboard access or a Dravo API key.
- A developer account on the platform and permission to create an app.
- An account that is eligible to publish: an Instagram professional account, a Facebook Page, or a normal X, LinkedIn or TikTok account as applicable.
- A platform app with the products and scopes listed in the relevant guide: Instagram, Facebook, X, LinkedIn, or TikTok.
The exact OAuth scopes come from Dravo's platform adapter, not from a free-form
field. GET /v1/oauth-apps returns the same list Dravo will put in the platform
authorization request.
Callback versus return URL
These URLs have different owners and must not be interchanged:
| URL | Called by | Purpose |
|---|---|---|
redirect_uri | Social platform | Sends the authorization code to Dravo. Register this in the platform console. |
return_url | Dravo | Sends the browser back to your product after Dravo has connected the account. Add it to allowed_return_urls; do not register it at the platform. |
Dravo has one public API deployment. Register these fixed callbacks:
| Platform | Callback to register |
|---|---|
https://api.dravo.dev/v1/oauth/instagram/callback | |
https://api.dravo.dev/v1/oauth/facebook/callback | |
| X | https://api.dravo.dev/v1/oauth/x/callback |
https://api.dravo.dev/v1/oauth/linkedin/callback | |
| TikTok | https://api.dravo.dev/v1/oauth/tiktok/callback |
Do not replace api.dravo.dev with your application domain. Treat each complete
URI as case-sensitive and keep its scheme, host and path exactly as shown.
1. Configure the platform
Create a web/server application in the platform console, enable its publishing product, add the scopes Dravo requests, and register the callback from the table above. Each platform exposes different client credentials and has different review rules, so follow its dedicated page before continuing:
- Configure Instagram Login
- Configure Facebook Login for Pages
- Configure X OAuth 2.0 with PKCE
- Configure LinkedIn products and OAuth
- Configure TikTok Login Kit and Direct Post
Use a confidential web application whenever the platform asks for an app type. Dravo exchanges codes server-side and stores a client secret; it is not a single-page or native OAuth client.
2. Save platform credentials
In the dashboard, open Connections, choose Add platform credentials, select the platform, and paste the platform's client identifier and secret. The modal shows the callback and scopes for the selected platform.
The equivalent API call is:
curl -X POST https://api.dravo.dev/v1/oauth-apps \
-H "Authorization: Bearer $DRAVO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"platform": "x",
"name": "Production X App",
"client_id": "YOUR_OAUTH_2_CLIENT_ID",
"client_secret": "YOUR_OAUTH_2_CLIENT_SECRET",
"allowed_return_urls": ["https://app.acme.com/settings/connections"]
}'The response contains three values worth checking before the first connection:
{ "id": "oa_1", "platform": "x", "redirect_uri": "https://api.dravo.dev/v1/oauth/x/callback", "scopes": [ "tweet.write", "tweet.read", "users.read", "offline.access", "media.write" ], "allowed_return_urls": [ "https://app.acme.com/settings/connections" ]}The secret is encrypted at rest and is never returned. Updating credentials with an empty or omitted secret preserves the stored value.
3. Get a connect URL
Ask Dravo for a connect URL. Pass oauth_app_id explicitly when you have more
than one credential set for the same platform.
curl --get "https://api.dravo.dev/v1/oauth/x/start" \
-H "Authorization: Bearer $DRAVO_API_KEY" \
--data-urlencode "oauth_app_id=oa_1" \
--data-urlencode "return_url=https://app.acme.com/settings/connections"{ "authorize_url": "https://twitter.com/i/oauth2/authorize?client_id=..."}Return an HTTP redirect to authorize_url or open it in the user's browser.
Do not call it server-to-server: the account owner must sign in and grant the
permissions. A return_url is accepted only when its origin matches and its
path starts with an entry in allowed_return_urls.
4. Handle the return
The platform redirects to Dravo's public callback. Dravo verifies signed
state, exchanges the authorization code, resolves the platform identity,
encrypts the token and creates the connected account. It then redirects the
browser to your return_url:
- Success:
https://app.acme.com/settings/connections?connected=x - Failure:
https://app.acme.com/settings/connections?oauth_error=<reason>
When no return_url is supplied, Dravo returns to
FRONTEND_URL/dashboard/connections. Do not treat the success query parameter
as your source of truth; query the accounts API after the browser returns.
5. Verify the connection
curl "https://api.dravo.dev/v1/accounts?platform=x" \
-H "Authorization: Bearer $DRAVO_API_KEY"Confirm that the account has connection_type: "oauth", the expected handle,
the intended oauth_app_id, and all required scopes. Then make a small test
post. Platform review restrictions can allow OAuth to succeed while still
blocking publishing, so authorization alone is not a complete production test.
Production checklist
- The callback returned by Dravo exactly matches the URI in the platform console; no frontend URL, wildcard, query string or fragment was substituted.
- The platform app uses its production credentials, is in the required live or production mode, and has completed any required review/audit.
- Every scope returned by Dravo is enabled for the platform app. Existing users reconnected after any scope change.
- Platform test users, app roles and publishable accounts are configured for pre-review testing.
allowed_return_urlscontains only narrow HTTPS routes you control.- The platform secret is stored only in Dravo or your backend, never browser code, source control or logs.
- A real text and/or media post was tested with the same app and account class that production will use.
Common failures
| Symptom | Likely cause | Fix |
|---|---|---|
| Platform reports a redirect mismatch | Callback differs by scheme, host, path, case or trailing slash. | Copy redirect_uri from GET /v1/oauth-apps and paste it unchanged into the platform console. |
Dravo returns return_url is not allowed | The frontend destination is not in the selected app's allowlist. | Add the narrow URL to allowed_return_urls or omit return_url. |
| Consent screen omits a scope | Product/permission is not enabled, or the app was changed after the token was issued. | Enable the product and permission, then reconnect the account. |
| OAuth succeeds but publishing is forbidden | App review, access tier, Page role, account type or audit is incomplete. | Follow the platform guide and test the platform endpoint requirements. |
| The wrong social account is connected | The browser reused an existing platform session. (Facebook connects every Page the user manages, one account each.) | Sign out/use a private window and verify the returned account(s) before publishing. |