Challenge data
Read and refresh the comments, likers and post metrics on a challenge post, and administer its attempts.
List stored comments
Get paginated comments stored for a challenge post.
Authorization
AuthorizationRequiredBearer <token>API token. Send it as Authorization: Bearer <API_TOKEN>.
In: header
Path Parameters
challengeIdRequiredintegerQuery Parameters
pageinteger1limitinteger20Comment list
Get latest post metrics
Returns the most recent metrics snapshot for the challenge post (likes, comments, shares, views).
data is the last successful scrape, so its fetchedAt alone cannot tell you whether the numbers are current — a challenge whose refreshes have been failing for days keeps returning its last good snapshot. Read lastRefresh for that: it records the most recent attempt and its outcome (success, rate_limited, error). If lastRefresh.attemptedAt is much newer than data.fetchedAt, the numbers are stale and something is failing.
lastRefresh is null if the challenge has never been refreshed since this tracking was introduced.
Authorization
AuthorizationRequiredBearer <token>API token. Send it as Authorization: Bearer <API_TOKEN>.
In: header
Path Parameters
challengeIdRequiredintegerLatest metrics plus the outcome of the last refresh attempt
Force-refresh post metrics
Fetches fresh metrics (Instagram post info or TikTok video info) and stores a new snapshot. Use this to get up-to-date like/comment/share/view counts.
Two success shapes. 200 means the snapshot was taken and is in the body. 202 means the scraping provider is rate limiting us, so the refresh has been queued and will run in the background — poll GET /admin/challenges/{challengeId}/metrics after the number of seconds given in retryAfterSeconds (also sent as the Retry-After header).
Only one background refresh exists per challenge at a time. status distinguishes the two cases: queued means this call created it, already_scheduled means one was already pending or running and nothing new was enqueued. Calling repeatedly is therefore safe and cheap — it will not stack jobs.
Cooldown. Each challenge can be refreshed at most once every 5 minutes; sooner returns 429 RATE_LIMITED with a Retry-After. The cooldown is per challenge, not per caller, so sweeping many challenges is unaffected — only re-refreshing the same one is. The cooldown is keyed on the challenge id itself, so /1, /01 and /1.0 share one budget rather than three. An id that is not a positive integer is rejected with 422 VALIDATION_ERROR before any provider call.
If the post cannot be read at all, the reason is propagated — see the ScrapingError schema.
Age-restricted Instagram posts are read through a fallback provider, so they normally return 200 with the counts. 422 POST_AGE_RESTRICTED now means both providers failed, and note that such a snapshot carries no viewCount — the fallback reports no play count even for a reel.
Authorization
AuthorizationRequiredBearer <token>API token. Send it as Authorization: Bearer <API_TOKEN>.
In: header
Path Parameters
challengeIdRequiredintegerFreshly fetched metrics
Force-refresh comments
Reads the post and stores what it finds, newest first, plus Instagram threaded replies on a best-effort basis. New comments are inserted; existing ones are matched on platform comment ID and left unchanged. Worth calling once when launching a campaign on a post that already has comments.
One call does not always reach the end of a large post. The call walks the newest comments, then works backwards through the history from where the last call stopped, and gives up after about four minutes. Call it again to carry on.
totalFetched is the number of comments stored for the post, not the number this call added. sweepStatus is swept when this call walked the comments, or in_progress when another read of the same post was already running, so this call left the walk to it — on Instagram the reply pass still runs either way. historyComplete reports whether the stored comments are as complete as they will get; false means there is older history still to fetch.
Once 6,000 comments are stored for a post, the walk back through older history stops. Newer comments carry on being stored.
If the post cannot be read, the reason is propagated — see the ScrapingError schema.
Authorization
AuthorizationRequiredBearer <token>API token. Send it as Authorization: Bearer <API_TOKEN>.
In: header
Path Parameters
challengeIdRequiredintegerRefresh result
Create attempt for a user (admin)
Create an attempt on behalf of a specific creator. Caller must be admin. Identify the creator by either userId (internal integer id) or externalId (customer-side identifier stored on users.externalId).
Authorization
AuthorizationRequiredBearer <token>API token. Send it as Authorization: Bearer <API_TOKEN>.
In: header
Request Body
application/jsonRequireduserIdintegerInternal user id. Mutually exclusive with externalId — provide one.
externalIdstringCustomer-side identifier stored on users.externalId. Mutually exclusive with userId — provide one.
Path Parameters
challengeIdRequiredintegerAttempt created
Get attempt by ID
Authorization
AuthorizationRequiredBearer <token>API token. Send it as Authorization: Bearer <API_TOKEN>.
In: header
Path Parameters
challengeIdRequiredintegerattemptIdRequiredintegerAttempt details
Progress attempt for a user (admin)
Advance an attempt's state on behalf of the attempt's owning creator. Caller must be admin. The owning user is resolved from the attempt row — no userId/externalId needed in the body.
Authorization
AuthorizationRequiredBearer <token>API token. Send it as Authorization: Bearer <API_TOKEN>.
In: header
Request Body
application/jsonRequiredactionRequiredstring"target_opened" | "claim_completion"Path Parameters
challengeIdRequiredintegerattemptIdRequiredintegerAttempt updated
Force-verify attempt
Moves an attempt straight to verified, schedules the reward, and sends creator.verified followed by reward.issued.
Every state except verified and rewarded can be force-verified, including failed_terminal — an attempt that has exhausted its retries is the main reason to reach for this route.
Authorization
AuthorizationRequiredBearer <token>API token. Send it as Authorization: Bearer <API_TOKEN>.
In: header
Path Parameters
challengeIdRequiredintegerattemptIdRequiredintegerAttempt force-verified
Redeliver outbound webhooks for attempt
Re-enqueues outbound brand webhooks (creator.verified, reward.issued, verification.failed) for an attempt. Use after a receiver outage to replay deliveries that exhausted their pg-boss retries. If events is omitted, every event eligible for the attempt's current state is redelivered (rewarded → both verified + reward; verified → verified only; failed_* → verification.failed). Caller must be admin.
Authorization
AuthorizationRequiredBearer <token>API token. Send it as Authorization: Bearer <API_TOKEN>.
In: header
Request Body
application/jsonOptionaleventsarray<string>Path Parameters
challengeIdRequiredintegerattemptIdRequiredintegerRedelivery enqueued
Get attempt by social handle
Look up a creator's attempt for a challenge by their social media handle (e.g. creator_jane or @creator_jane). Returns null if no attempt found.
Authorization
AuthorizationRequiredBearer <token>API token. Send it as Authorization: Bearer <API_TOKEN>.
In: header
Path Parameters
challengeIdRequiredintegerhandleRequiredstringAttempt for this handle (or null)
Fetch likers for a challenge's Instagram post
Starts an asynchronous fetch of the likers of the Instagram post this challenge already references — the post is derived from the challenge, so no shortcode/URL is supplied. Returns 202 immediately; poll the status endpoint for progress.
Coverage caveat: this uses a public/no-cookie scraper, so the number of fetched liker profiles may be lower than Instagram's visible like count. Only supported for Instagram challenges.
Authorization
AuthorizationRequiredBearer <token>API token. Send it as Authorization: Bearer <API_TOKEN>.
In: header
Path Parameters
challengeIdRequiredintegerQuery Parameters
maxCountintegerMax likers to fetch. Defaults to 1000.
1000Minimum: 1Maximum: 5000Fetch accepted and started
Status of the latest likers fetch for a challenge
Authorization
AuthorizationRequiredBearer <token>API token. Send it as Authorization: Bearer <API_TOKEN>.
In: header
Path Parameters
challengeIdRequiredintegerLatest fetch status, or null if none has been requested
List stored likers for a challenge (paginated)
Returns likers from the most recent completed fetch for the challenge. Empty if no fetch has succeeded yet.
Authorization
AuthorizationRequiredBearer <token>API token. Send it as Authorization: Bearer <API_TOKEN>.
In: header
Path Parameters
challengeIdRequiredintegerQuery Parameters
pageinteger1limitinteger20Maximum: 100Liker rows
Last updated on