Encore API for tools
Schedulers, analytics and CRM tools can work with a creator’s account once the creator allows them. Creators see exactly what a tool asks for and can disconnect it at any time; staff review every tool before other creators can connect it.
How it works
- Register your app: name, website, redirect addresses (https) and the scopes it needs. You get a client id and a secret, shown once.
- While it is in development, only your own creator account can connect it. Submit it for review to open it to every creator.
- Send the creator to the consent page with PKCE:
/oauth/authorize?response_type=code&client_id=…&redirect_uri=…&scope=posts:read%20posts:write&state=…&code_challenge=…&code_challenge_method=S256 - Exchange the code from your redirect address for tokens, from your server, with the secret and the code verifier:
POST /api/oauth/token(grant_type=authorization_code). - Call the API with the access token (it lasts an hour). Refresh it with the refresh token; every refresh gives you a new pair, and an old refresh token used again stops everything.
Scopes
| profile:read | See your profile, tiers and public stats |
| posts:read | See your posts and whether they are published |
| posts:write | Publish and schedule posts with files already approved in your vault |
| analytics:read | See your analytics |
| earnings:read | See your earnings and balances (never your payout details) |
| fans:read | See your fans’ pseudonyms, subscriptions and spend (never e-mail addresses) |
There is no scope to message fans, on purpose: fans must always know who writes to them. Payout details, e-mail addresses and identities are never available.
Endpoints
| GET | /api/v1/me | profile:read |
| GET | /api/v1/posts | posts:read |
| POST | /api/v1/posts | posts:write |
| GET | /api/v1/analytics?days=30 | analytics:read |
| GET | /api/v1/earnings | earnings:read |
| GET | /api/v1/fans | fans:read |
curl -H "Authorization: Bearer enc_at_…" https://encore.example/api/v1/posts
Errors follow OAuth: 401 invalid_token, 403 insufficient_scope, 429 rate_limited (120 calls a minute per creator). Fans have an id that is your app’s own, so different apps cannot match up the same fan.
Webhooks
Instead of asking the API again and again, set a receiver in your app’s settings and we post events to it. An event goes to your app only for creators who connected it, and only if the connection has the scope that would let you read the same data.
| sale.created | A fan paid: subscription, unlock, tip, ticket, order or call | earnings:read |
| fan.subscribed | A fan followed or subscribed to a tier | fans:read |
| post.published | A post went live, including scheduled ones | posts:read |
| connection.revoked | The creator disconnected your app: delete what you keep about them | — |
Each request carries Encore-Webhook-Id (the same on every retry, so you can skip duplicates), Encore-Webhook-Timestamp and Encore-Signature: t=timestamp,v1=HMAC-SHA256 of "timestamp.body" with your signing secret. Reject signatures older than 300 seconds.
import { createHmac, timingSafeEqual } from 'node:crypto';
function verify(rawBody, header, secret) {
const { t, v1 } = Object.fromEntries(header.split(',').map((p) => p.split('=')));
if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;
const expected = createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex');
return expected.length === v1.length && timingSafeEqual(Buffer.from(expected), Buffer.from(v1));
}Answer 2xx within 10 seconds. Otherwise we retry after 1, 5, 30 minutes, 2, 6 and 24 hours; after 5 deliveries in a row fail for good, the webhook is paused and you are notified. Redirects are not followed, and receivers on private networks are refused. Fans in events have the same app-specific id as in the API.