eencoreSign up

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.

Register an app

How it works

  1. Register your app: name, website, redirect addresses (https) and the scopes it needs. You get a client id and a secret, shown once.
  2. While it is in development, only your own creator account can connect it. Submit it for review to open it to every creator.
  3. 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
  4. 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).
  5. 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:readSee your profile, tiers and public stats
posts:readSee your posts and whether they are published
posts:writePublish and schedule posts with files already approved in your vault
analytics:readSee your analytics
earnings:readSee your earnings and balances (never your payout details)
fans:readSee 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/meprofile:read
GET/api/v1/postsposts:read
POST/api/v1/postsposts:write
GET/api/v1/analytics?days=30analytics:read
GET/api/v1/earningsearnings:read
GET/api/v1/fansfans: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.createdA fan paid: subscription, unlock, tip, ticket, order or callearnings:read
fan.subscribedA fan followed or subscribed to a tierfans:read
post.publishedA post went live, including scheduled onesposts:read
connection.revokedThe 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.