Summary and recommendation
The Reddit Ads API (base URL: https://ads-api.reddit.com/api/v3) exposes full CRUD control over ad account user membership via OAuth 2.0.
Authentication is handled through Reddit's core OAuth infrastructure (https://www.reddit.com/api/v1/access_token) - not the Ads API domain itself - a distinction that catches integrators off guard.
The two required scopes are ads:read for GET operations and ads:manage for POST, PATCH, and DELETE operations on user records.
The user object surfaces id, username, email, role (enum: ACCOUNT_ADMIN, CAMPAIGN_MANAGER, VIEWER), status (enum: ACTIVE, PENDING, REMOVED), account_id, created_at, and updated_at.
Pagination is cursor-based using the after parameter with a maximum page size of 100.
Rate limit thresholds are not publicly documented;
the API returns HTTP 429 with X-RateLimit-Remaining and X-RateLimit-Reset headers, but no Retry-After header - implement exponential backoff accordingly.
SCIM 2.0 is not available.
No IdP connectors (Okta, Entra ID, Google Workspace, OneLogin) are officially supported.
All provisioning must go through the Ads API user endpoints or the UI.
Webhooks are also absent;
detecting membership changes requires polling GET /accounts/{account_id}/users.
API quick reference
| Has user API | Yes |
| Auth method | OAuth 2.0 (authorization_code or client_credentials grant) |
| Base URL | Official docs |
| SCIM available | No |
| SCIM plan required | N/A |
Authentication
Auth method: OAuth 2.0 (authorization_code or client_credentials grant)
Setup steps
- Register an application at https://www.reddit.com/prefs/apps to obtain a client_id and client_secret.
- Request authorization from the ad account owner via the OAuth 2.0 authorization endpoint: https://www.reddit.com/api/v1/authorize with the required scopes.
- Exchange the authorization code for an access token at https://www.reddit.com/api/v1/access_token.
- Include the access token as a Bearer token in the Authorization header of all Ads API requests.
- Refresh tokens using the refresh_token grant when the access token expires.
Required scopes
| Scope | Description | Required for |
|---|---|---|
| ads:read | Read access to ad account data, campaigns, and user associations. | GET operations on ad account users and account metadata. |
| ads:manage | Write access to manage ad accounts, including inviting and removing users. | POST/DELETE operations on ad account user membership. |
User object / data model
| Field | Type | Description | On create | On update | Notes |
|---|---|---|---|---|---|
| id | string | Unique identifier for the user within the Reddit Ads platform. | system-generated | immutable | Reddit user t2_ prefixed ID. |
| username | string | Reddit username of the user. | required | immutable | Must be an existing Reddit account. |
| string | Email address associated with the Reddit account. | not settable via API | not settable via API | Managed by Reddit core account settings, not the Ads API. | |
| role | string (enum) | Role of the user within the ad account. Values: ACCOUNT_ADMIN, CAMPAIGN_MANAGER, VIEWER. | required | updatable | Determines permissions within the ad account. |
| status | string (enum) | Invitation or membership status. Values: ACTIVE, PENDING, REMOVED. | system-set to PENDING on invite | read-only | User must accept invite to become ACTIVE. |
| account_id | string | The ad account ID this user membership belongs to. | required (path param) | immutable | Format: t2_xxxxxx or account UUID depending on endpoint. |
| created_at | ISO 8601 timestamp | Timestamp when the user was added or invited to the ad account. | system-generated | immutable | |
| updated_at | ISO 8601 timestamp | Timestamp of the last update to the user record. | system-generated | system-updated |
Core endpoints
List users on an ad account
- Method: GET
- URL:
https://ads-api.reddit.com/api/v3/accounts/{account_id}/users - Watch out for: Only users with ads:read scope and membership in the account can retrieve this list.
Request example
GET /api/v3/accounts/t2_abc123/users
Authorization: Bearer {access_token}
Response example
{
"data": [
{"id": "t2_xyz", "username": "redditor1", "role": "ACCOUNT_ADMIN", "status": "ACTIVE"}
],
"after": null
}
Invite a user to an ad account
- Method: POST
- URL:
https://ads-api.reddit.com/api/v3/accounts/{account_id}/users - Watch out for: The invited user receives a Reddit notification and must accept the invite; status remains PENDING until accepted.
Request example
POST /api/v3/accounts/t2_abc123/users
Authorization: Bearer {access_token}
Content-Type: application/json
{"username": "newredditor", "role": "CAMPAIGN_MANAGER"}
Response example
{
"data": {
"id": "t2_newuser",
"username": "newredditor",
"role": "CAMPAIGN_MANAGER",
"status": "PENDING"
}
}
Update a user's role on an ad account
- Method: PATCH
- URL:
https://ads-api.reddit.com/api/v3/accounts/{account_id}/users/{user_id} - Watch out for: Requires ads:manage scope. Cannot demote the last ACCOUNT_ADMIN.
Request example
PATCH /api/v3/accounts/t2_abc123/users/t2_xyz
Authorization: Bearer {access_token}
Content-Type: application/json
{"role": "VIEWER"}
Response example
{
"data": {
"id": "t2_xyz",
"role": "VIEWER",
"status": "ACTIVE"
}
}
Remove a user from an ad account
- Method: DELETE
- URL:
https://ads-api.reddit.com/api/v3/accounts/{account_id}/users/{user_id} - Watch out for: Cannot remove the sole ACCOUNT_ADMIN. The deleted user loses access immediately.
Request example
DELETE /api/v3/accounts/t2_abc123/users/t2_xyz
Authorization: Bearer {access_token}
Response example
HTTP 204 No Content
Get a specific user on an ad account
- Method: GET
- URL:
https://ads-api.reddit.com/api/v3/accounts/{account_id}/users/{user_id} - Watch out for: Returns 404 if the user is not a member of the specified account.
Request example
GET /api/v3/accounts/t2_abc123/users/t2_xyz
Authorization: Bearer {access_token}
Response example
{
"data": {
"id": "t2_xyz",
"username": "redditor1",
"role": "ACCOUNT_ADMIN",
"status": "ACTIVE"
}
}
Rate limits, pagination, and events
- Rate limits: Reddit Ads API enforces rate limits per OAuth token. Official docs note limits but do not publish exact per-minute/per-hour numbers publicly.
- Rate-limit headers: Yes
- Retry-After header: No
- Rate-limit notes: The API returns HTTP 429 when rate limits are exceeded. Official docs reference rate-limit response headers (X-RateLimit-Remaining, X-RateLimit-Reset) but exact thresholds are not published. Retry-After header behavior is not explicitly documented.
- Pagination method: cursor
- Default page size: 100
- Max page size: 100
- Pagination pointer: after
| Plan | Limit | Concurrent |
|---|---|---|
| Standard (all authenticated apps) | Not publicly specified in official docs | 0 |
- Webhooks available: No
- Webhook notes: Reddit Ads API does not document a webhook or event-subscription system for user-management events as of the current official documentation.
- Alternative event strategy: Poll the GET /accounts/{account_id}/users endpoint periodically to detect membership changes.
SCIM API status
- SCIM available: No
- SCIM version: Not documented
- Plan required: N/A
- Endpoint: Not documented
Limitations:
- Reddit Ads does not offer a SCIM 2.0 endpoint.
- No IdP (Okta, Entra ID, Google Workspace, OneLogin) connectors are officially supported for SCIM provisioning.
- User provisioning must be performed via the Ads API user endpoints or the Reddit Ads UI.
Common scenarios
Three automation scenarios cover the primary identity lifecycle for Reddit Ads.
Onboarding: POST to /api/v3/accounts/{account_id}/users with the invitee's Reddit username and target role.
Status initializes as PENDING;
poll GET /accounts/{account_id}/users/{user_id} until it transitions to ACTIVE.
The invitee must accept a Reddit in-platform notification - no email is sent, and the API cannot create Reddit accounts for users who lack one.
Offboarding with staged access reduction: PATCH the user's role to VIEWER first to strip write access immediately, confirm via GET, then DELETE to fully revoke membership.
The DELETE is rejected if the target is the sole ACCOUNT_ADMIN - ensure a second admin exists before executing.
Access audit: Authenticate with ads:read, paginate GET /accounts/{account_id}/users using the after cursor until it returns null, then filter by status and role.
PENDING records appear alongside ACTIVE members;
audit logic must explicitly separate them.
Ad account IDs may appear as Reddit t2_ user IDs or as UUIDs depending on account type - verify format in the account object before constructing requests.
Onboard a new team member to an ad account
- Authenticate via OAuth 2.0 with ads:manage scope.
- POST to /api/v3/accounts/{account_id}/users with the new user's Reddit username and desired role (e.g., CAMPAIGN_MANAGER).
- Poll GET /api/v3/accounts/{account_id}/users/{user_id} until status transitions from PENDING to ACTIVE (user must accept the Reddit invite).
- Confirm ACTIVE status before granting the user access to campaign resources.
Watch out for: If the invitee does not have a Reddit account, the invite will fail. The API does not send email invitations; the user receives a Reddit in-platform notification.
Downgrade a departing employee's access before removal
- PATCH /api/v3/accounts/{account_id}/users/{user_id} with role: VIEWER to restrict write access immediately.
- Confirm the role change via GET /api/v3/accounts/{account_id}/users/{user_id}.
- DELETE /api/v3/accounts/{account_id}/users/{user_id} to fully remove the user from the account.
Watch out for: Ensure at least one other ACCOUNT_ADMIN exists before removing or demoting the current admin, or the DELETE will be rejected.
Audit all users across an ad account
- Authenticate with ads:read scope.
- GET /api/v3/accounts/{account_id}/users and collect all user records.
- If the response includes an after cursor, repeat the request with ?after={cursor} until after is null.
- Filter results by status (ACTIVE, PENDING) and role to produce an access report.
Watch out for: PENDING users still appear in the list; include status filtering in your audit logic to distinguish active members from outstanding invitations.
Why building this yourself is a trap
The Reddit Ads API integrates cleanly into an identity graph when its structural constraints are treated as first-class design inputs rather than edge cases.
The absence of SCIM and webhooks means the identity graph must own the polling cadence and state reconciliation for every account - PENDING invitations are a persistent source of drift if not explicitly tracked and expired.
Because OAuth tokens are issued against Reddit's core infrastructure but consumed by the Ads API domain, token management pipelines must handle both endpoints without conflating their scopes or base URLs.
The undocumented rate limit is the sharpest operational risk at scale: an integration auditing many ad accounts in parallel will hit HTTP 429 without a predictable ceiling to plan against. Exponential backoff with jitter is non-negotiable.
The sole-admin constraint (ACCOUNT_ADMIN cannot be removed if last on the account) must be enforced in offboarding logic before issuing DELETE - the API will reject the call, but a silent failure in an automated pipeline is worse than a pre-flight check.
Teams building against this API should treat the status field as the authoritative signal for access state and never assume a POST invite equals active access.
Automate Reddit Ads workflows without one-off scripts
Stitchflow builds and maintains end-to-end IT automation across your SaaS stack, including apps without APIs. Built for exactly how your company works, with human approvals where they matter.