Appearance
API - Getting Started
The EasyDonate API lets you read your account data and control your timer widget programmatically. It is a closed alpha gated behind the OPENAPI_ALPHA whitelist - ask the team to be added before you start.
The full reference (auto-generated OpenAPI 3) is rendered with Redoc at /docs.
Authentication
Every request uses the same header:
Authorization: Bearer <token>There are two kinds of token:
| Token | Type | Acts as | Where you get it |
|---|---|---|---|
Bearer ezdn_v1_<cuid> | Personal API key | Your own account | Dashboard -> Developer -> API Keys |
Bearer <jwt> | OAuth access token | The consenting user | OAuth flow (below) |
API keys are opaque strings prefixed with ezdn_v1_. OAuth access tokens are short-lived signed JWTs, so they look like xxxxx.yyyyy.zzzzz rather than a prefixed string.
Tokens are scoped - a request is rejected with 403 if the token lacks the scope the endpoint requires.
Scopes
| Scope | Grants |
|---|---|
read:profile | Account identity (PII redacted) |
read:donations | Donation transactions, stats, charts, trends, export |
read:widgets | Widget configs + data + timer/connection status |
write:timer | Control the running timer (play/pause/reset/adjust) |
read:subscription | Your EasyDonate plan, limits, sponsorships |
read:creator | Public creator lookups + your own creator stats |
read:channels | Donation channel status/type (secrets stripped) |
Quick start with an API key
Create a key in the dashboard, pick the scopes you need, then:
bash
curl https://easydonate.app/api/v1/me \
-H "Authorization: Bearer ezdn_v1_xxxxxxxxxxxxxxxx"List recent donations:
bash
curl "https://easydonate.app/api/v1/donations?page=1" \
-H "Authorization: Bearer ezdn_v1_xxxxxxxxxxxxxxxx"Control the timer (needs write:timer):
bash
curl -X POST https://easydonate.app/api/v1/widgets/timer/control \
-H "Authorization: Bearer ezdn_v1_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"action":"adjust","ms":60000}'Every response uses the standard envelope:
json
{ "statusCode": 200, "data": {} }OAuth2 (act on behalf of other users)
For apps that act on behalf of EasyDonate users, register an application (Dashboard -> Developer -> Applications) to receive a client_id and client_secret. The flow is Authorization Code + PKCE (PKCE is mandatory).
- Send the user to the authorize screen:
https://easydonate.app/oauth/authorize?client_id=<client_id>
&redirect_uri=<your_callback>
&scope=read:profile read:donations
&state=<random>
&code_challenge=<S256_challenge>
&code_challenge_method=S256The user logs in and approves. EasyDonate redirects to
redirect_uri?code=<code>&state=<state>.Exchange the code for tokens from your backend:
bash
curl -X POST https://easydonate.app/oauth/token \
-H "Content-Type: application/json" \
-d '{
"grant_type": "authorization_code",
"code": "<code>",
"client_id": "<client_id>",
"client_secret": "<client_secret>",
"redirect_uri": "<your_callback>",
"code_verifier": "<verifier>"
}'Response:
json
{
"access_token": "<jwt>",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "ezdn_v1_rt_...",
"scope": "read:profile read:donations"
}The access_token is a signed JWT - pass it verbatim in the Authorization header. The refresh_token is an opaque string prefixed with ezdn_v1_rt_.
- Call the API with the access token:
bash
curl https://easydonate.app/api/v1/me \
-H "Authorization: Bearer <jwt>"- Refresh when it expires (the refresh token rotates - store the new one):
bash
curl -X POST https://easydonate.app/oauth/token \
-H "Content-Type: application/json" \
-d '{
"grant_type": "refresh_token",
"refresh_token": "ezdn_v1_rt_...",
"client_id": "<client_id>",
"client_secret": "<client_secret>"
}'- Revoke a token (or remove the connection):
bash
curl -X POST https://easydonate.app/oauth/revoke \
-H "Content-Type: application/json" \
-d '{"token":"ezdn_v1_rt_...","client_id":"<client_id>","client_secret":"<client_secret>"}'Access tokens live 1 hour; refresh tokens 30 days. Access tokens are stateless JWTs and cannot be revoked individually - revoke the refresh token (or remove the connection) to cut off an app. Unverified apps may connect at most 20 users
- request verification in the dashboard to lift the cap.
Rate limits
Requests are limited to 60 per minute per credential. Responses carry X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset; exceeding the limit returns 429.