Core resources
Programs
Browse the merchant catalogue, apply on behalf of a channel, track approval state.
The program object
A program is a merchant campaign as LinkApprove presents it: the upstream network's terms, normalised into one shape so you do not care which network it came from.
idintegerStable LinkApprove identifier. Mint tracking links against this.
merchantNamestring | nullThe brand as the merchant wants it displayed.
merchantDomainstring | nullThe merchant's site, without www. Deep links must stay on it or a subdomain of it.
categorystring | nullThe upstream network's own category as a lowercase slug, e.g. apparel_footwear_accessories. Null when the network sends none.
payoutTypeenumcps pays a share of the sale, cpc pays per click.
payoutstring | nullThe most you can earn: the program's highest commission tier with LinkApprove's cut already taken off, so it is your 70% share of the network's rate. A two-decimal string such as "8.00", read together with payoutUnit. Null when the network publishes no rate.
payoutUnitenum | nullpercent for a revenue share, fixed for a flat amount. Null when the network does not say which.
currencystring | nullCurrency of the payout, when the network states one; null otherwise. ISO 4217, e.g. USD.
cookieDaysinteger | nullAttribution window in days. A conversion inside it credits your click. Null when the network does not say.
approvalTypeenum | nullauto approves the instant you apply; manual goes to the LinkApprove team for review. Null when the network does not say.
statusenumYour application state for this program: not_applied, pending, approved, rejected, paused, suspended or expired. Scoped to channelId when you pass it.
supportsDeepLinksbooleanWhether a tracking link for this program accepts a destinationUrl.
descriptionstring | nullRetrieve only. The merchant's own pitch.
regionsstring[]Retrieve only. ISO 3166-1 alpha-2 codes the merchant ships or converts in.
logoUrlstring | nullRetrieve only. The merchant's logo.
status is about you, not the merchant
status reflects your application state for the program on your channels, not whether the campaign itself is live. A program that is removed or deactivated stops appearing in the list, and retrieving it returns 404.{
"id": 4821,
"merchantName": "Northpeak Outdoors",
"merchantDomain": "northpeak.com",
"category": "sports_outdoor",
"payoutType": "cps",
"payout": "8.00",
"payoutUnit": "percent",
"currency": "USD",
"cookieDays": 30,
"approvalType": "manual",
"status": "approved",
"supportsDeepLinks": true,
"description": "Technical outerwear and camping gear.",
"regions": ["US", "CA"],
"logoUrl": "https://cdn.linkapprove.com/merchants/4821.png"
}List programs
https://api.linkapprove.com/v1/programsprograms:readReturns a paginated list of every campaign available to your account. Filters combine with AND.
pageinteger1-based page number. Defaults to 1.
sizeintegerResults per page, 1–100. Defaults to 10.
searchstringMatches merchant name or domain.
categorystringThe network's category as a slug: lowercased, & decoded, every run of other characters turned into _. An open set, e.g. apparel_footwear_accessories or sports_outdoor.
payoutTypeenumcps or cpc.
approvalTypeenumauto or manual. Useful for finding programs you can start on today.
channelIdintegerReport status for this channel. Without it, status is the best state across all your channels.
statusenumOnly programs in this state: not_applied, pending, approved, rejected, paused, suspended or expired. Matches the status each program comes back with, so it follows channelId too.
Paginating the whole catalogue
- Read
pagesfrom the first response and walkpageup to it. Do not guess at an end. - Use
size=100for a full sync. A 13,700-campaign catalogue is 137 requests. At 120 a minute that takes just over a minute, so pace your requests or expect a429and honour itsRetry-After. - Pagination is offset-based, newest first. Programs added or removed while you sync shift rows between pages, so a row can repeat or be skipped, so dedupe by
id.
curl "https://api.linkapprove.com/v1/programs?payoutType=cps&page=1&size=10" \
-H "Authorization: Bearer $LINKAPPROVE_API_KEY"https://api.linkapprove.com/v1/programs?payoutType=cps&page=1&size=10Held in this tab's session storage only, and reused by every runner on the site.
This panel replays the documented sample response and does not call the API. Copy a code sample to send a real request with your key.
Retrieve a program
https://api.linkapprove.com/v1/programs/{id}programs:readReturns a single program with the same fields as a list entry, plus description, regions and logoUrl. Pass channelId to scope status to one channel.
An unknown or unavailable ID returns 404 with program_not_found. We do not distinguish "does not exist" from "not yours". Both are a 404.
curl "https://api.linkapprove.com/v1/programs/4821" \
-H "Authorization: Bearer $LINKAPPROVE_API_KEY"https://api.linkapprove.com/v1/programs/4821Held in this tab's session storage only, and reused by every runner on the site.
This panel replays the documented sample response and does not call the API. Copy a code sample to send a real request with your key.
Apply to a program
https://api.linkapprove.com/v1/programs/applicationsprograms:writeApplications are made per channel. The same program can be approved on one of your sites and rejected on another, which is why channelId is required rather than inferred.
programIdintegerrequiredThe program you want to run.
channelIdintegerrequiredAn approved channel of yours that has completed verification. Applications are per channel, not per account.
notestringOptional, up to 500 characters. Accepted for forward compatibility but not stored. Nobody reads it today.
What happens next
approvalType: "auto"comes backapprovedwithdecidedAtequal toappliedAt, and you can mint links in the same script run.approvalType: "manual"comes backpendingwithdecidedAt: nullwhile the LinkApprove team reviews it. PollGET /programs/{id}?channelId=untilstatuschanges.rejectionReasonis alwaysnullfor now.- Applying again for the same program and channel returns
409duplicate_applicationwith the existingapplicationIdand itsstatus, whatever that status is, rejected included.
When it fails
404program_not_found: no such program.404channel_not_found: the channel does not exist or is not yours.403channel_not_verified: the channel is not approved, or has a verification step it has not completed.
A rejection is final through the API
curl -X POST "https://api.linkapprove.com/v1/programs/applications" \
-H "Authorization: Bearer $LINKAPPROVE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"programId": 4821,
"channelId": 12,
"note": "Outdoor gear reviews, 40k monthly readers, US and CA."
}'https://api.linkapprove.com/v1/programs/applicationsHeld in this tab's session storage only, and reused by every runner on the site.
This panel replays the documented sample response and does not call the API. Copy a code sample to send a real request with your key.
List applications
https://api.linkapprove.com/v1/programs/applicationsprograms:readReturns every application you have made, newest first, across all your channels. Use it to pick up decisions on manual programs in one call instead of polling each program.
statusenumpending, approved, rejected, paused, suspended or expired.
programIdintegerOnly applications to this program.
channelIdintegerOnly applications from this channel.
pageinteger1-based page number. Defaults to 1.
sizeintegerResults per page, 1–100. Defaults to 10.
Each row is the application object you got back when applying, plus merchantName. decidedAt is when the application left pending, or null while it is still waiting.
curl "https://api.linkapprove.com/v1/programs/applications?page=1&size=10" \
-H "Authorization: Bearer $LINKAPPROVE_API_KEY"https://api.linkapprove.com/v1/programs/applications?page=1&size=10Held in this tab's session storage only, and reused by every runner on the site.
This panel replays the documented sample response and does not call the API. Copy a code sample to send a real request with your key.