OAuth
Sign in with AnythingAuth.
AnythingAuth lets another site sign members in with their anything-advertising.com account. Members register applications in the Applications tool and receive a client ID. Confidential applications also receive a client secret.
The service implements OAuth 2.0 authorization code with a UserInfo endpoint. It does not implement OpenID Connect and does not issue ID tokens.
Applications can also request payments from members with AnythingPay. See Payments.
Endpoints
| Endpoint | Use |
|---|---|
https://anything-advertising.com/oauth/authorize | Authorization. GET. |
https://anything-advertising.com/oauth/token | Token. POST, form-encoded. |
https://anything-advertising.com/oauth/userinfo | UserInfo. GET with Authorization: Bearer <token>. |
https://anything-advertising.com/oauth/transactions | Paged transaction history. Requires the transactions scope. |
https://anything-advertising.com/oauth/revoke | Revokes an access or refresh token. |
https://anything-advertising.com/oauth/introspect | Reports whether a token is active and its scope. |
https://anything-advertising.com/.well-known/oauth-authorization-server | Server metadata. |
Authorization request
Send the member to the authorization endpoint with these parameters:
| Parameter | Value |
|---|---|
response_type | code |
client_id | The application's client ID. |
redirect_uri | One of the application's registered redirect URIs. |
scope | Space-separated scopes. Defaults to profile. |
state | An unguessable value, returned unchanged on the callback. |
code_challenge | BASE64URL(SHA256(code_verifier)). |
code_challenge_method | S256 |
prompt | consent shows the consent screen even when the member has already approved the scopes. Optional. |
https://anything-advertising.com/oauth/authorize?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=https%3A%2F%2Fexample.com%2Fcallback&scope=profile%20email&state=RANDOM_STATE&code_challenge=CODE_CHALLENGE&code_challenge_method=S256
Token exchange
Exchange the returned code at the token endpoint with a form-encoded POST. Send client_id and client_secret in the body, or use HTTP Basic with the same pair. Public clients send client_id and omit the secret.
curl -X POST https://anything-advertising.com/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d grant_type=authorization_code \
-d code=AUTHORIZATION_CODE \
-d redirect_uri=https://example.com/callback \
-d client_id=YOUR_CLIENT_ID \
-d client_secret=YOUR_CLIENT_SECRET \
-d code_verifier=CODE_VERIFIER
To refresh a token, send the refresh token with grant_type=refresh_token:
curl -X POST https://anything-advertising.com/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d grant_type=refresh_token \
-d refresh_token=REFRESH_TOKEN \
-d client_id=YOUR_CLIENT_ID \
-d client_secret=YOUR_CLIENT_SECRET
A successful exchange returns bearer credentials. Store them on your server, never in a page or a log:
{
"access_token": "ACCESS_TOKEN",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "REFRESH_TOKEN",
"scope": "profile email"
}
UserInfo
Request the member's claims with the access token as a bearer credential:
curl https://anything-advertising.com/oauth/userinfo \
-H "Authorization: Bearer ACCESS_TOKEN"
Example response with the profile, email, balance, and roles scopes:
{
"sub": "482",
"username": "example",
"display_name": "Example Member",
"picture": "https://cdn.example.com/avatars/482.webp",
"profile_url": "https://anything-advertising.com/u/example.482",
"email": "[email protected]",
"email_verified": true,
"balance": {
"points": 1250,
"usd": 12.5,
"currency": "USD",
"amount": 12.5,
"display": "$12.50"
},
"roles": [
{"name": "Member", "color": "#3b6fd4"}
]
}
Transaction history
With the transactions scope, the full Points ledger is available in pages. UserInfo returns the newest 50 entries plus pagination metadata; use this endpoint for older pages and filters.
curl "https://anything-advertising.com/oauth/transactions?per_page=25&page=2&since=2026-01-01" \
-H "Authorization: Bearer ACCESS_TOKEN"
| Parameter | Use |
|---|---|
page | Page number, starting at 1. Default 1. |
per_page | 25 or 50. Default 50. |
since | ISO 8601 date or timestamp. Inclusive. |
until | ISO 8601 date or timestamp. Inclusive. A date means the end of that day in UTC. |
direction | credit or debit. |
reason | Exact ledger reason, for example payout_request. |
order | newest (default) or oldest. |
Each entry carries a readable type, direction, Points amount and balance, and timestamp. Amounts also include the member's formatted display value.
{
"transactions": [
{
"id": 9201,
"type": "Cash-out requested",
"reason": "payout_request",
"direction": "debit",
"amount": {"points": -500, "display": "$-5.00"},
"balance": {"points": 1250, "display": "$12.50"},
"created_at": "2026-10-01T12:00:00Z"
}
],
"pagination": {
"page": 1,
"per_page": 50,
"total": 120,
"pages": 3,
"has_prev": false,
"has_next": true
},
"filters": {
"since": null,
"until": null,
"direction": null,
"reason": null,
"order": "newest"
}
}
App storage
With the storage scope, an application can keep private JSON data for each member, such as game saves, progress, or preferences. Each application has its own space per member.
See the App storage guide for the endpoints, examples, limits, and member controls.
Scopes
When you register an application, you choose the scopes it may request. An authorization request may ask for any subset of that set; requesting anything else is refused with invalid_scope. Changing the selection revokes existing tokens and asks members to approve the app again.
| Scope | Grants |
|---|---|
profile | sub, username, display name, profile picture, profile link |
email | Email address and verification status |
currency | Display currency code, name and symbol |
language | Language and locale preference |
timezone | Preferred time zone |
appearance | Theme and accent preference |
region | Country and location, when set |
balance | Points balance and approximate value |
transactions | Paged Points transaction history, amounts and balances |
roles | Role badges shown on the profile |
stats | Reputation, post and thread counts, follower counts, join date |
storage | A private key/value store for this application and member |
Security
redirect_urimust exactly match one of the URIs registered for the application. Wildcards and partial matches are refused.- Send
statewith every authorization request and compare it on the callback. It prevents a forged callback from being accepted. - Public clients must use PKCE with S256.
- Keep client secrets on the server. Never ship one in a browser or mobile app.
- Refresh tokens rotate on every use. The old token stops working. Presenting it again revokes the whole token family.
- Access tokens are bearer credentials. Send them only over HTTPS and keep them out of logs.
- App storage is bound to the token's application and member. The API never accepts either identity in the request.
- Members can review and revoke an application's access at any time in Settings → Connected apps.
- Application names are self-registered and are not verified. Only authorize applications you trust.