Skip to main content

Reddit Ads

The Reddit Ads source syncs an ad account, campaigns, ads, ad groups, and daily account, campaign, ad group, and ad performance metrics from the Reddit Ads API v3 for a single ad account.

Prerequisites​

  • A Reddit Ads account with at least one ad account, and a Reddit user who can access the ad account you want to sync.
  • The ID of the ad account you want to sync.
  • If you use the Use your own Reddit app authentication option:
    • A Reddit developer app, which gives you the app ID and secret this connector uses as its OAuth client ID and client secret. Only business admins with a verified Reddit account can create one.
    • An OAuth refresh token for that app, authorized with the adsread scope.

Set up the Reddit Ads source​

The connector offers two Authentication options:

  • Authenticate with Reddit: Sign in to Reddit from Airbyte, and Airbyte obtains the refresh token for you. This is the default option in Airbyte Cloud. You don't need your own developer app, so skip Steps 1 and 2.
  • Use your own Reddit app: Enter the client ID, client secret, and refresh token of a Reddit developer app you manage. Use this option in self-managed Airbyte, or if you already have a developer app. Complete Steps 1 and 2 first.

Sources created before version 0.2.0 move to Use your own Reddit app automatically and keep their existing client ID, client secret, and refresh token, so they need no action.

Step 1: Create a developer app​

  1. In Reddit Ads Manager, open your business's Developer Applications page.
  2. Select Add Apps > Create an app, then fill in the app name, About URL, redirect URL, and primary contact. Reddit requires a redirect URL even though the connector never uses it interactively, so any URL you control works, such as https://example.com/oauth/callback.
  3. Select Create App. Reddit shows the app ID and secret. Copy both. The app ID is your OAuth Client ID and the secret is your OAuth Client Secret.

If you already have a Reddit app under Preferences > Apps, you can select Add Apps > Migrate an existing app instead. Migrating limits the app's scope to the Ads API.

For details, see Reddit's Create a Developer Application guide.

Step 2: Get a refresh token​

The connector authenticates with the OAuth refresh token grant, so you need a long-lived refresh token. Get one with the authorization code flow described in Reddit's authentication guide.

  1. Sign in to Reddit as the user whose ads data you want to sync, then open the following URL in a browser, replacing the placeholders:

    https://www.reddit.com/api/v1/authorize?client_id=YOUR_APP_ID&response_type=code&state=airbyte&redirect_uri=YOUR_REDIRECT_URL&duration=permanent&scope=adsread

    Set duration to permanent. A temporary authorization doesn't return a refresh token, and the connector can't sync without one. adsread is the only scope the connector needs.

  2. Select Allow. Reddit redirects to your redirect URL with a code query parameter. Copy the code, removing any trailing #_ characters. The code expires after 10 minutes and works only once.

  3. Exchange the code for tokens:

    curl -X POST https://www.reddit.com/api/v1/access_token \
    -H 'content-type: application/x-www-form-urlencoded' \
    -A 'YOUR_USER_AGENT' \
    -u 'YOUR_APP_ID:YOUR_APP_SECRET' \
    -d 'grant_type=authorization_code&code=YOUR_CODE&redirect_uri=YOUR_REDIRECT_URL'
  4. Copy the refresh_token value from the response. That's your OAuth Refresh Token. The connector uses it to obtain access tokens itself, so you don't need the access_token value.

Step 3: Find your ad account ID​

In Reddit Ads Manager, open Business Manager > Assets > Ad Accounts. The ID appears under the ad account's name and starts with a2_. You can also call List Ad Accounts By Business with the token you just created.

Step 4: Configure the source in Airbyte​

  1. Under Authentication, choose one option:

    • Authenticate with Reddit: Select Authenticate your Reddit Ads account, sign in to Reddit as a user who can access the ad account you want to sync, and select Allow.
    • Use your own Reddit app: Enter the OAuth Client ID, OAuth Client Secret, and OAuth Refresh Token from Steps 1 and 2.
  2. Enter the Ad Account ID from Step 3.

  3. Set the remaining optional fields:

    • User Agent: Optional. A descriptive user agent in the format platform:app_id:version (by /u/username). For example, airbyte:reddit-ads-sync:v1.0 (by /u/your-username). If you leave it empty, the connector sends an Airbyte user agent. Reddit heavily throttles default user agents such as Python/urllib or Java.
    • Start Date: Optional. The earliest data to sync, in RFC 3339 format with a UTC offset, such as 2024-05-11T00:00:00Z. It applies to the incremental streams: it's the earliest modified_at for ad, ad_group, and campaign, and the earliest report date for the four report streams. If you leave it empty, those streams start 24 months before the current sync.
    • Number of Concurrent Workers: Optional. The number of requests the connector runs in parallel, from 1 to 10. The default is 3. Higher values can speed up syncs, but they make Reddit rate limiting more likely.
    • Report Lookback Window (Days): Optional. How many whole days before the last synced report date to re-read on each incremental sync, from 0 to 30. The default is 7 days.

Supported streams​

StreamAPI endpointPrimary keyIncremental cursor
ad_accountGET /api/v3/ad_accounts/{ad_account_id}idNone
adGET /api/v3/ad_accounts/{ad_account_id}/adsidmodified_at
ad_groupGET /api/v3/ad_accounts/{ad_account_id}/ad_groupsidmodified_at
campaignGET /api/v3/ad_accounts/{ad_account_id}/campaignsidmodified_at
ad_account_reportPOST /api/v3/ad_accounts/{ad_account_id}/reportsaccount_id, datedate
campaign_reportPOST /api/v3/ad_accounts/{ad_account_id}/reportscampaign_id, datedate
ad_group_reportPOST /api/v3/ad_accounts/{ad_account_id}/reportsad_group_id, datedate
ad_reportPOST /api/v3/ad_accounts/{ad_account_id}/reportsad_id, datedate

All eight streams read from the single ad account you configure. ad_account supports full refresh; the other seven streams also support incremental sync. To sync more than one ad account, create one source per account.

campaign_report, ad_account_report, ad_group_report, and ad_report return one row per campaign, account, ad group, or ad per UTC day, respectively, with delivery and conversion metrics such as impressions, clicks, spend, reach, frequency, and per-objective conversion counts and values.

Sync behavior and limitations​

  • Report metrics use micro-units. Reddit returns spend, cpc, cpv, ecpm, and the conversion_*_ecpa metrics multiplied by 1,000,000, and the conversion_*_total_value metrics multiplied by 100. The connector loads these values unchanged, so divide them in your destination before reporting on currency amounts.
  • Recent report data changes after it lands. Reddit says metrics can take up to 6 hours to stabilize, and it applies late conversions for earlier hours or days in a daily refresh. Each incremental report-stream sync re-reads the last synced date plus the configured Report Lookback Window (Days). Conversion metrics follow your ad account's attribution window, so raise the lookback to cover it, up to 30 days, if you need late conversions on older days. Use Incremental | Append + Deduped so re-read rows replace the earlier ones. The row for the current UTC day stays partial until a sync runs after that day ends.
  • Report streams re-read days without data. A report stream saves the date of the latest row it read as its state. If an ad account has no delivery after that date, each incremental sync requests all later days again, and an account that has never had delivery requests the full 24 months on every sync.
  • Refresh campaign_report after upgrading from a version earlier than 0.3.0. Earlier versions requested report windows with gaps, so any sync that covered more than three days, including the first sync, left some dates missing or partial. Each incremental sync also re-sent the row for the day before the last synced date with only that day's last 7 hours of data. The lookback window only corrects recent days, so run a refresh with Refresh stream and retain records. In Incremental | Append mode, keep the latest row for each campaign_id and date. Don't use Refresh stream and remove records or Clear: Reddit only serves the last 24 months of report data, so older rows can't be synced again. Full refresh syncs correct themselves on the next sync.
  • Report history has a limit. Delivery data goes back 24 months, and reach and frequency data start in June 2024. If you set Start Date earlier than 24 months ago, report streams still start 24 months before the current sync, because Reddit rejects requests for older report data. ad, ad_group, and campaign aren't clamped.
  • Report streams use fixed breakdowns. Each report stream breaks metrics down by its entity ID and UTC date. ad_group_report and ad_report are also broken down by campaign, so their rows include campaign_id. ad_account_report sets account_id to your Ad Account ID. To get the ad group of an ad_report row, join ad on ad_id. Breakdowns such as country or region, and custom conversion events by name, aren't available.
  • Versions earlier than 0.0.9 synced only the first page of each stream. Reddit returns the next page token URL-encoded, and earlier versions passed it back without decoding it, so every stream stopped after its first page. If you upgraded from an earlier version and records are missing in your destination, clear the affected streams and run a new sync.
  • Start Date filtering happens after the fetch. For ad, ad_group, and campaign, the Reddit API has no server-side filter on modified_at, so the connector requests every record in the ad account on each sync and discards those modified before your cursor value. Sync duration scales with the size of the account, not with the amount of new data.

Performance considerations​

Reddit applies rate limits per Reddit app, authorized user, and endpoint group, so sources that use the same app and Reddit user share those limits. The connector calls endpoints in two groups:

Reddit rate limit groupEndpointsStreamsQuota
ads-campaign-management-readGet Ad Account, List Ads, List Ad Groups, List Campaignsad_account, ad, ad_group, campaign400 requests per 60 seconds
ads-reportingGet A Reportad_account_report, campaign_report, ad_group_report, ad_report60 requests per 60 seconds

The connector throttles its own requests to stay within these quotas. It only counts the requests it makes itself, so other sources that use the same app and Reddit user can still push it over the limit. Each report stream requests contiguous three-day UTC windows per call, so a long backfill makes many report calls.

By default, the connector runs up to 3 requests in parallel. You can change this with Number of Concurrent Workers, up to a maximum of 10. If syncs hit rate limits often, lower this value.

The connector retries 429 and 5xx responses up to 10 times with exponential backoff. For the full list of policies, see Reddit's rate limiting documentation.

The connector reuses an access token until it expires, then refreshes it. If a request still fails with 401, the connector refreshes the token and retries that request. If Reddit returns a new refresh token during a refresh, the connector saves it to the source configuration, so you don't have to rotate it yourself.

Troubleshooting​

ErrorCause and fix
Refresh token was rejected by the OAuth providerReddit's token endpoint rejected the refresh token or the client credentials. If you use Authenticate with Reddit, select Authenticate your Reddit Ads account again. If you use Use your own Reddit app, confirm the OAuth Client ID and Client Secret, then get a new refresh token with duration=permanent.
Reddit denied access to ad account (HTTP 403)The refresh token lacks the adsread scope, or the Reddit user who authorized it can't access this ad account. Re-authenticate, or get a new refresh token with the adsread scope, while signed in as a user with access to the ad account.
Reddit could not find ad account (HTTP 404) or Reddit rejected the ad account IDThe Ad Account ID is wrong. Find your ad account ID, which starts with a2_, and update the source.
Reddit rejected the request as invalid (HTTP 400)Reddit rejected the request for a reason unrelated to the ad account. The error message includes the explanation Reddit returned.

Configuration​

InputTypeDescriptionDefault Value
credentialsobjectAuthentication: Authenticate with Reddit (auth_type: OAuth2.0) or Use your own Reddit app (auth_type: OwnApp).
credentials.client_idstringOAuth Client ID. The client ID of your Reddit app.
credentials.client_secretstringOAuth Client Secret. The client secret of your Reddit app.
credentials.refresh_tokenstringOAuth Refresh Token.
start_timestringOptional UTC start date applied to the incremental streams, in YYYY-MM-DDTHH:MM:SSZ format. A value earlier than 24 months ago is clamped for report streams, because Reddit only serves report data for the last 24 months.24 months before the current date
user_agentstringOptional. User Agent. A unique and descriptive user agent string in the format: platform:app_id:version (by /u/yourusername). If empty, the connector uses an Airbyte user agent.airbyte:source-reddit-ads:v1
ad_account_idstringThe Reddit Ads account ID to sync, shown in Reddit Ads Manager, for example a2_abc123.
num_workersintegerNumber of concurrent workers. Higher values speed up syncs but increase the chance of Reddit rate limiting.3
report_lookback_window_daysintegerOptional. Number of whole days before the last synced report date to re-read for late-attributed conversions and restated metrics (0–30).7

Streams​

Stream NamePrimary KeyPaginationSupports Full SyncSupports Incremental
ad_accountidNo pagination✅❌
adidDefaultPaginator✅✅
ad_groupidDefaultPaginator✅✅
campaignidDefaultPaginator✅✅
ad_account_reportaccount_id.dateDefaultPaginator✅✅
campaign_reportcampaign_id.dateDefaultPaginator✅✅
ad_group_reportad_group_id.dateDefaultPaginator✅✅
ad_reportad_id.dateDefaultPaginator✅✅

IP allow list​

If you use Airbyte Cloud and your organization restricts access to specific IPs, add the Airbyte Cloud IP addresses to your allow list.

Reference​

Config fields reference

Field
Type
Property name
string
ad_account_id
object
credentials
integer
num_workers
integer
report_lookback_window_days
string
start_time
string
user_agent

Changelog​

Expand to review
VersionDatePull RequestSubject
0.4.02026-10-1688964Add ad_account, ad_group, ad_account_report, ad_group_report and ad_report streams; show Reddit's field-level reason in HTTP 400 error messages
0.3.02026-10-1588963Fix campaign_report windows that skipped one day in every three and overwrote earlier days with partial data; add a configurable report lookback window
0.2.02026-10-1488145Add OAuth (Authenticate with Reddit) for Airbyte Cloud with automatic config migration to a credentials object; make User Agent optional
0.1.12026-10-0688015Update dependencies
0.1.02026-10-0587043Show actionable errors for rejected refresh tokens or client credentials, invalid ad account IDs, and 400/403/404 responses, add a client-side API budget and configurable concurrency, add suggested streams, make spec titles human-readable, and add unit tests
0.0.122026-09-2987338Update dependencies
0.0.112026-09-2286789Update dependencies
0.0.102026-09-1586198Update dependencies
0.0.92026-09-0984850Fix pagination so every stream syncs all pages instead of only the first
0.0.82026-09-0885629Update dependencies
0.0.72026-08-1884348Enable acceptance test suite with GSM test secrets
0.0.62026-08-1884725Update dependencies
0.0.52026-08-1184089Update dependencies
0.0.42026-08-0483603Update dependencies
0.0.32026-08-0483266Stop refreshing the access token before every request, and refresh it before retrying a 401. Make start_time optional, apply it to all three streams, and default it to 24 months before the sync; clamp campaign_report to Reddit's 24-month reporting window
0.0.22026-07-2883100Update dependencies
0.0.12026-07-2781399Initial release by @Ella6882 via Connector Builder