Getting Started
Guides
Affiliates
Conversions
Affiliate Teams
SCALE
Coupons
Payouts
Other
Webhooks
MCP Server (AI)
Complete REST API documentation. All endpoints use JSON and require Bearer token authentication.
/api/v1/campaigns
List Campaigns
Returns all campaigns for the authenticated merchant, with pagination.
Parameters
| page | number | Page number (default: 1) |
| limit | number | Results per page (default: 25, max: 100) |
Example
curl https://linkjolt.io/api/v1/campaigns \
-H "Authorization: Bearer lj_pk_your_key"Response
{
"data": [
{
"id": "PAbeJtXF39gDMUPYGZqZX",
"name": "Pro Campaign",
"trackingCode": "7PtIfIqd",
"status": "active",
"commissionType": "percentage",
"commissionValue": "20",
"conversions": 47,
"revenue": "12350.00",
"createdAt": "2026-01-15T10:30:00Z"
}
],
"pagination": { "page": 1, "limit": 25, "total": 3, "totalPages": 1 }
}/api/v1/campaigns
Create Campaign
Create a campaign programmatically. It is created on your API key's brand with an auto-generated tracking code and returned in the same shape as Get Campaign. Requires the Ultimate or Scale plan. Live keys only (campaigns are live objects, so test keys are rejected).
Parameters
| name* | string | Campaign name (min 2 characters) |
| commissionType* | string | "percentage" or "fixed" |
| commissionValue* | number | Commission rate (percent) or fixed amount |
| status | string | "active" (default), "inactive", or "expired" |
| description | string | Campaign description |
| targetUrl | string | Destination URL affiliates link to |
| autoApproveAffiliates | boolean | Auto-approve affiliates who join (default false) |
| isPublic | boolean | List in the Discovery marketplace (default true) |
| enableRecurringCommissions | boolean | Pay commission on renewals (Ultimate/Scale) |
Example
curl https://linkjolt.io/api/v1/campaigns \
-X POST \
-H "Authorization: Bearer lj_pk_live_your_key" \
-H "Content-Type: application/json" \
-d '{"name":"API Campaign","commissionType":"percentage","commissionValue":20}'Response
{
"data": {
"id": "PAbeJtXF39gDMUPYGZqZX",
"name": "API Campaign",
"trackingCode": "7PtIfIqd",
"status": "active",
"commissionType": "percentage",
"commissionValue": "20",
"conversions": 0,
"revenue": null,
"createdAt": "2026-07-12T10:30:00Z",
"affiliateCount": 0
}
}/api/v1/campaigns/:id
Get Campaign
Fetch a single campaign by ID with full details, affiliate count, and the 10 most recent conversions.
Parameters
| id* | string | Campaign ID (path parameter) |
Example
curl https://linkjolt.io/api/v1/campaigns/CAMPAIGN_ID \
-H "Authorization: Bearer lj_pk_your_key"Response
{
"data": {
"id": "PAbeJtXF39gDMUPYGZqZX",
"name": "Pro Campaign",
"trackingCode": "7PtIfIqd",
"commissionType": "percentage",
"commissionValue": 20,
"affiliateCount": 12,
"recentConversions": [ /* ... */ ],
"createdAt": "2026-01-15T10:30:00Z"
}
}/api/v1/affiliates
List Affiliates
List affiliates across your campaigns. Filter by campaignId or status. Excludes rejected affiliates.
Parameters
| campaignId | string | Filter by campaign ID |
| status | string | Filter: approved, pending |
| page | number | Page number |
| limit | number | Results per page (max 100) |
| sort | string | e.g. name:asc, joinedAt:desc |
Example
curl "https://linkjolt.io/api/v1/affiliates?status=approved" \
-H "Authorization: Bearer lj_pk_your_key"Response
{
"data": [
{
"id": "aff_xyz",
"name": "Jane Smith",
"email": "jane@example.com",
"status": "approved",
"campaignId": "camp_abc",
"campaignName": "Pro Campaign",
"joinedAt": "2026-03-10T09:00:00Z"
}
],
"pagination": { "page": 1, "limit": 25, "total": 12, "totalPages": 1 }
}/api/v1/affiliates/:id
Get Affiliate
Fetch a single affiliate with all their campaign associations and aggregated earnings across your campaigns.
Parameters
| id* | string | Affiliate ID (path parameter) |
Example
curl https://linkjolt.io/api/v1/affiliates/AFFILIATE_ID \
-H "Authorization: Bearer lj_pk_your_key"Response
{
"data": {
"id": "aff_xyz",
"name": "Jane Smith",
"email": "jane@example.com",
"campaigns": [
{ "campaignId": "camp_abc", "campaignName": "Pro", "status": "approved", "joinedAt": "..." }
],
"earnings": {
"totalRevenue": 2350.00,
"totalCommissions": 470.00,
"totalConversions": 12,
"uniqueClicks": 340
}
}
}/api/v1/affiliates/invite
Invite Affiliate
Send an email invitation to an affiliate for a specific campaign. Enforces your plan's affiliate limit.
Parameters
| email* | string | Affiliate email address |
| name | string | Affiliate name (optional) |
| campaignId* | string | Campaign to invite them to |
Example
curl https://linkjolt.io/api/v1/affiliates/invite \
-X POST \
-H "Authorization: Bearer lj_pk_your_key" \
-H "Content-Type: application/json" \
-d '{"email":"jane@example.com","campaignId":"camp_abc"}'Response
{
"data": {
"id": "inv_abc",
"email": "jane@example.com",
"name": "Jane Smith",
"campaignId": "camp_abc",
"status": "pending",
"isTest": false,
"createdAt": "2026-04-14T12:00:00Z"
}
}/api/v1/affiliates
Create Affiliate
Create an affiliate directly (no email invite, no sign-up) and attach them to a campaign, auto-approved. The affiliate has no login account: they are a tracking and payout record you pay directly. Returns a ready-to-share tracking link. Enforces your plan's affiliate limit.
Parameters
| email* | string | Affiliate email address (globally unique) |
| name | string | Affiliate name (defaults to the email if omitted) |
| campaignId* | string | Campaign to add them to |
Example
curl https://linkjolt.io/api/v1/affiliates \
-X POST \
-H "Authorization: Bearer lj_pk_your_key" \
-H "Content-Type: application/json" \
-d '{"email":"jane@example.com","name":"Jane Smith","campaignId":"camp_abc"}'Response
{
"data": {
"id": "aff_abc",
"name": "Jane Smith",
"email": "jane@example.com",
"status": "approved",
"campaignId": "camp_abc",
"campaignName": "Summer Launch",
"trackingLink": "https://linkjolt.io/redirect?tc=SUMMER24&aff=aff_abc",
"createdVia": "api",
"joinedAt": "2026-06-22T12:00:00Z"
}
}/api/v1/conversions
List Conversions
Returns conversions with optional filters for status, campaign, affiliate, and date range. Each item also carries payout-tracking fields (payoutMethod, payoutDate, stripeTransferId), populated once the commission has been paid.
Parameters
| status | string | Filter: pending, approved, paid, rejected |
| campaignId | string | Filter by campaign ID |
| affiliateId | string | Filter by affiliate ID |
| from | date | Start date (ISO 8601) |
| to | date | End date (ISO 8601) |
| page | number | Page number |
| limit | number | Results per page |
Example
curl "https://linkjolt.io/api/v1/conversions?status=pending&from=2026-04-01" \
-H "Authorization: Bearer lj_pk_your_key"Response
{
"data": [
{
"id": "stripe_7PtIfIqd_1234567890",
"campaignId": "PAbeJtXF39gDMUPYGZqZX",
"affiliateId": "lRCbRMSvBcGg4HszLCXLr",
"amount": "100.00",
"taxAmount": null,
"commission": "20.00",
"currency": "usd",
"status": "pending",
"conversionType": "one_time",
"payoutMethod": null,
"payoutDate": null,
"stripeTransferId": null,
"createdAt": "2026-04-12T06:58:07Z"
}
],
"pagination": { "page": 1, "limit": 25, "total": 47, "totalPages": 2 }
}/api/v1/conversions
Create Conversion
Manually create a conversion record. Commission is calculated automatically based on campaign settings (including tiered commissions if enabled).
Parameters
| campaignId* | string | Campaign ID |
| affiliateId* | string | Affiliate ID |
| amount* | number | Sale amount in dollars |
| orderId | string | Unique order ID for deduplication |
| clickId | string | LinkJolt click ID (enables fraud detection) |
| customerEmail | string | Customer email (enables the self-referral fraud check; shown on the commissions page) |
| customerName | string | Customer name (shown on the commissions page) |
Example
curl -X POST https://linkjolt.io/api/v1/conversions \
-H "Authorization: Bearer lj_pk_your_key" \
-H "Content-Type: application/json" \
-d '{"campaignId":"abc","affiliateId":"xyz","amount":99}'Response
{
"data": {
"id": "conv_abc123",
"campaignId": "PAbeJtXF39gDMUPYGZqZX",
"affiliateId": "aff_xyz",
"amount": 99.00,
"commission": 19.80,
"currency": "usd",
"status": "pending",
"orderId": "invoice-2026-001",
"conversionType": "one_time",
"isTest": false,
"createdAt": "2026-04-15T10:30:00Z"
}
}/api/v1/conversions/:id
Get Conversion
Fetch one conversion by id. Same field set as the list endpoint, including taxAmount, payout state, and isTest.
Parameters
| id* | string | Conversion ID (path parameter) |
Example
curl https://linkjolt.io/api/v1/conversions/CONVERSION_ID \
-H "Authorization: Bearer lj_pk_your_key"Response
{
"data": {
"id": "conv_abc",
"campaignId": "camp_1",
"campaignName": "Pro Plan Launch",
"affiliateId": "aff_123",
"amount": 250.00,
"taxAmount": null,
"commission": 50.00,
"currency": "USD",
"status": "approved",
"orderId": "ord_551",
"customerEmail": "buyer@example.com",
"customerName": "Alex Doyle",
"conversionType": "one_time",
"parentConversionId": null,
"isTest": false,
"payoutMethod": null,
"payoutDate": null,
"stripeTransferId": null,
"createdAt": "2026-08-01T10:15:00.000Z"
}
}/api/v1/conversions/:id
Update Conversion
Approve or reject a conversion. Cannot change conversions that have already been paid.
Parameters
| id* | string | Conversion ID (path parameter) |
| status* | string | New status: "approved" or "rejected" |
Example
curl https://linkjolt.io/api/v1/conversions/CONVERSION_ID \
-X PATCH \
-H "Authorization: Bearer lj_pk_your_key" \
-H "Content-Type: application/json" \
-d '{"status":"approved"}'Response
{
"data": {
"id": "conv_abc",
"status": "approved",
"amount": 100.00,
"commission": 20.00,
"updatedAt": "2026-04-14T12:00:00Z"
}
}Group affiliates into reusable rosters with per-member commission overrides, revenue targets, and merchant-approved bonus awards. Every Teams endpoint, reads included, requires a Scale-priced account; other plans receive 403 plan_insufficient. Teams has no test mode: team write endpoints reject test keys with 403 test_mode_unsupported, and team reads return nothing for test keys. Approving a bonus award with a write key moves money on the same trust model as approving a commission with PATCH /conversions/:id: any write key can do it, and there is no separate payout scope. Leader target proposals and proposal review stay in the dashboard, not the API.
/api/v1/teams
List Teams
List your Affiliate Teams with a summary of each: member count, assigned-campaign count, how many members have a custom commission rate, the active revenue target (with percent to goal), and any awards awaiting approval. Scale plan only.
Parameters
| page | number | Page number (default: 1) |
| limit | number | Results per page (default: 25, max: 100) |
Example
curl https://linkjolt.io/api/v1/teams \
-H "Authorization: Bearer lj_pk_live_your_key"Response
{
"data": [
{
"id": "team_7bKq2mZ",
"name": "EU Growth Squad",
"currency": "usd",
"leaderAffiliateId": "aff_5Yh1Qn",
"baseCommissionType": "percentage",
"baseCommissionValue": "25",
"memberCount": 8,
"campaignCount": 2,
"customRateCount": 3,
"activeTarget": { "name": "July revenue push", "pct": 62.5, "label": "$6,250 of $10,000" },
"pendingAwards": { "count": 2, "total": 500 },
"createdAt": "2026-07-01T09:00:00Z"
}
],
"pagination": { "page": 1, "limit": 25, "total": 4, "totalPages": 1 }
}/api/v1/teams
Create Team
Create an Affiliate Team. Set an optional team-level base commission that applies to every member on every assigned campaign (member and per-campaign overrides take precedence). A team chat thread is created automatically. Assign a leader later with Update Team. Scale plan, live keys only.
Parameters
| name* | string | Team name (1 to 120 characters) |
| currency | string | 3-letter currency for the team's targets and awards (default: usd) |
| baseCommissionType | string | "percentage" or "fixed" (required if baseCommissionValue is set) |
| baseCommissionValue | number | Team base rate. Percent capped at 100; fixed capped at 100000 |
Example
curl https://linkjolt.io/api/v1/teams \
-X POST \
-H "Authorization: Bearer lj_pk_live_your_key" \
-H "Content-Type: application/json" \
-d '{"name":"EU Growth Squad","currency":"usd","baseCommissionType":"percentage","baseCommissionValue":25}'Response
{
"data": {
"id": "team_7bKq2mZ",
"name": "EU Growth Squad",
"currency": "usd",
"leaderAffiliateId": null,
"baseCommissionType": "percentage",
"baseCommissionValue": "25",
"memberCount": 0,
"campaignCount": 0,
"createdAt": "2026-07-15T10:30:00Z"
}
}/api/v1/teams/:id
Get Team
Fetch one team with its full roster (members with their derived leader/member role and whether they are a headless affiliate), assigned campaigns (with the team's per-campaign base rate and the campaign's own rate for reference), and a summary of its goals. Scale plan only.
Parameters
| id* | string | Team ID (path parameter) |
Example
curl https://linkjolt.io/api/v1/teams/TEAM_ID \
-H "Authorization: Bearer lj_pk_live_your_key"Response
{
"data": {
"id": "team_7bKq2mZ",
"name": "EU Growth Squad",
"currency": "usd",
"leaderAffiliateId": "aff_5Yh1Qn",
"baseCommissionType": "percentage",
"baseCommissionValue": "25",
"memberCount": 2,
"campaignCount": 1,
"members": [
{ "affiliateId": "aff_5Yh1Qn", "name": "Jane Smith", "email": "jane@example.com", "role": "leader", "isHeadless": false },
{ "affiliateId": "aff_8Rt3Wm", "name": "Marco Rossi", "email": "marco@example.com", "role": "member", "isHeadless": false }
],
"campaigns": [
{
"campaignId": "camp_9Fk2Lp",
"name": "Summer Launch",
"baseCommissionType": "percentage",
"baseCommissionValue": "30",
"campaignCommissionType": "percentage",
"campaignCommissionValue": "20"
}
],
"goals": [
{ "id": "goal_2Nw6Vx", "name": "July revenue push", "status": "active", "metric": "revenue", "targetValue": "10000", "periodMode": "monthly" }
],
"createdAt": "2026-07-01T09:00:00Z"
}
}/api/v1/teams/:id
Update Team
Update a team's name, base commission, or leader. The leader must be a current, non-headless member. The team currency can only be changed while the team has no goals: once any goal exists it is locked (409) so historic targets and awards stay in one currency. PATCH returns an acknowledgement; GET /api/v1/teams/:id returns the full updated team. Scale plan, live keys only.
Parameters
| id* | string | Team ID (path parameter) |
| name | string | New team name (1 to 120 characters) |
| currency | string | 3-letter currency. Locked once the team has any goal |
| baseCommissionType | string | "percentage" or "fixed" |
| baseCommissionValue | number | Team base rate (percent <=100, fixed <=100000) |
| leaderAffiliateId | string | Affiliate ID of the leader; must be a current non-headless member. Send null to clear |
Example
curl https://linkjolt.io/api/v1/teams/TEAM_ID \
-X PATCH \
-H "Authorization: Bearer lj_pk_live_your_key" \
-H "Content-Type: application/json" \
-d '{"leaderAffiliateId":"aff_5Yh1Qn"}'Response
{
"data": {
"id": "team_7bKq2mZ",
"updated": true
}
}/api/v1/teams/:id
Delete Team
Delete a team. Refused with 409 team_has_awards if the team has any bonus award history, so a delete can never destroy financial records. When allowed, every membership is unlinked first (members' commission rates revert to the campaign base) and the team chat thread becomes a read-only archive. Scale plan, live keys only.
Parameters
| id* | string | Team ID (path parameter) |
Example
curl https://linkjolt.io/api/v1/teams/TEAM_ID \
-X DELETE \
-H "Authorization: Bearer lj_pk_live_your_key"Response
{
"data": {
"id": "team_7bKq2mZ",
"deleted": true
}
}/api/v1/teams/:id/members
Add Team Members
Add up to 100 affiliates to a team in one call. Each affiliate must already have an approved (active) relationship with your brand; affiliates with no brand relationship, a pending or suspended relation, a test affiliate, or otherwise ineligible ones are skipped. The response returns counts (added, alreadyMembers, skipped) plus a per-id results array where each entry has an outcome (added, already_member, or skipped) and, when skipped, a reason. Added members are materialized onto all of the team's campaigns. Scale plan, live keys only.
Parameters
| id* | string | Team ID (path parameter) |
| affiliateIds* | string[] | Affiliate IDs to add (1 to 100) |
Example
curl https://linkjolt.io/api/v1/teams/TEAM_ID/members \
-X POST \
-H "Authorization: Bearer lj_pk_live_your_key" \
-H "Content-Type: application/json" \
-d '{"affiliateIds":["aff_5Yh1Qn","aff_8Rt3Wm"]}'Response
{
"data": {
"added": 2,
"alreadyMembers": 1,
"skipped": 1,
"results": [
{ "affiliateId": "aff_5Yh1Qn", "outcome": "added" },
{ "affiliateId": "aff_8Rt3Wm", "outcome": "already_member" },
{ "affiliateId": "aff_1Kp6Vc", "outcome": "skipped", "reason": "relation_suspended" }
]
}
}/api/v1/teams/:id/members/:affiliateId
Remove Team Member
Remove one affiliate from a team. Their team linkage and any commission override are cleared together, so their rate reverts to the campaign base. If they were the team leader, the leader pointer is cleared. Scale plan, live keys only.
Parameters
| id* | string | Team ID (path parameter) |
| affiliateId* | string | Affiliate ID to remove (path parameter) |
Example
curl https://linkjolt.io/api/v1/teams/TEAM_ID/members/AFFILIATE_ID \
-X DELETE \
-H "Authorization: Bearer lj_pk_live_your_key"Response
{
"data": {
"teamId": "team_7bKq2mZ",
"affiliateId": "aff_8Rt3Wm",
"removed": true
}
}/api/v1/teams/:id/campaigns
Assign Campaign to Team
Assign one of your campaigns to a team, optionally with a team-level base rate for that campaign. Existing members are materialized onto the campaign (auto-approved); the response returns the tally of what changed. Scale plan, live keys only.
Parameters
| id* | string | Team ID (path parameter) |
| campaignId* | string | Campaign ID (must belong to your brand) |
| baseCommissionType | string | "percentage" or "fixed" base rate for this campaign |
| baseCommissionValue | number | Base rate value (percent <=100, fixed <=100000) |
Example
curl https://linkjolt.io/api/v1/teams/TEAM_ID/campaigns \
-X POST \
-H "Authorization: Bearer lj_pk_live_your_key" \
-H "Content-Type: application/json" \
-d '{"campaignId":"camp_9Fk2Lp","baseCommissionType":"percentage","baseCommissionValue":30}'Response
{
"data": {
"teamId": "team_7bKq2mZ",
"campaignId": "camp_9Fk2Lp",
"created": true,
"tally": { "created": 2, "linked": 0, "already": 1, "rejected": 0, "conflict": 0 }
}
}/api/v1/teams/:id/campaigns/:campaignId
Unassign Campaign from Team
Remove a campaign from a team. Every member's team linkage and override on that campaign is cleared together, reverting them to the campaign base rate. Scale plan, live keys only.
Parameters
| id* | string | Team ID (path parameter) |
| campaignId* | string | Campaign ID (path parameter) |
Example
curl https://linkjolt.io/api/v1/teams/TEAM_ID/campaigns/CAMPAIGN_ID \
-X DELETE \
-H "Authorization: Bearer lj_pk_live_your_key"Response
{
"data": {
"teamId": "team_7bKq2mZ",
"campaignId": "camp_9Fk2Lp",
"removed": true
}
}/api/v1/teams/:id/overrides
Set Commission Overrides
Set per-member custom commission rates for up to 100 members on one campaign. Overrides are dimensioned by (campaign, affiliate): a rate applies only on the named campaign. Any override bypasses volume tiers. Send the campaign and the members to update together. Scale plan, live keys only.
Parameters
| id* | string | Team ID (path parameter) |
| campaignId* | string | Campaign the override applies to |
| affiliateIds* | string[] | Team members to update (1 to 100) |
| commissionType* | string | "percentage" or "fixed" (required when commissionValue is set) |
| commissionValue* | number | Override rate (percent <=100, fixed <=100000) |
| recurringValue | number | Optional recurring-commission override value |
Example
curl https://linkjolt.io/api/v1/teams/TEAM_ID/overrides \
-X POST \
-H "Authorization: Bearer lj_pk_live_your_key" \
-H "Content-Type: application/json" \
-d '{"campaignId":"camp_9Fk2Lp","affiliateIds":["aff_5Yh1Qn"],"commissionType":"percentage","commissionValue":40}'Response
{
"data": {
"campaignId": "camp_9Fk2Lp",
"updated": 3,
"skipped": ["aff_1Kp6Vc"]
}
}/api/v1/teams/:id/goals
List Team Goals
List a team's revenue or conversion targets with, for each active goal, the current-period progress (aggregate and per-member contributions in the team currency, plus any amounts excluded because they were in a different currency) and per-status award tallies. Scale plan only.
Parameters
| id* | string | Team ID (path parameter) |
Example
curl https://linkjolt.io/api/v1/teams/TEAM_ID/goals \
-H "Authorization: Bearer lj_pk_live_your_key"Response
{
"data": [
{
"id": "goal_2Nw6Vx",
"scope": "team",
"campaignId": null,
"name": "July revenue push",
"metric": "revenue",
"targetValue": "10000",
"periodMode": "monthly",
"periodStart": "2026-07-01T00:00:00Z",
"periodEnd": null,
"bonusType": "flat",
"bonusValue": "500",
"bonusTiers": null,
"bonusCap": null,
"bonusScope": "team",
"bonusSplit": "equal",
"bonusVisibility": "all",
"status": "active",
"refundSafeDays": 14,
"progress": {
"periodKey": "2026-07",
"aggregate": 6250,
"byMember": [
{ "affiliateId": "aff_5Yh1Qn", "contribution": 4100 },
{ "affiliateId": "aff_8Rt3Wm", "contribution": 2150 }
],
"excludedByCurrency": { "eur": { "count": 2, "amount": 300 } }
},
"awards": [
{ "status": "paid", "count": 3, "total": 1500 }
],
"createdAt": "2026-07-01T09:00:00Z",
"updatedAt": "2026-07-15T08:00:00Z"
}
]
}/api/v1/teams/:id/goals
Create Team Goal
Create a revenue or conversion target with a bonus pool paid to the team when the target is hit and the refund-safe window closes. Goals are created active. A team can have at most 10 goals that are not ended (409 too_many_goals). Scale plan, live keys only.
Parameters
| id* | string | Team ID (path parameter) |
| name* | string | Goal name |
| metric | string | "revenue" (default) or "conversions" |
| targetValue* | number | Target amount or count (up to 100,000,000) |
| periodMode | string | "monthly" (default) or "one_time" |
| scope | string | "team" (default) or "campaign" |
| campaignId | string | Required when scope is "campaign" |
| bonusType | string | "flat" (default), "tiered", or "percent_over" |
| bonusValue | number | Bonus amount (flat / percent_over), up to 100,000 |
| bonusTiers | array | For "tiered": up to 10 [{ threshold, amount }] |
| bonusCap | number | Optional cap on the total bonus pool |
| bonusScope | string | "team" (default, split among members) or "leader" |
| bonusSplit | string | "equal" (default) or "proportional" |
| bonusVisibility | string | "all" (default) or "leaders" |
| refundSafeDays | number | Days awards stay provisional for refunds (7 to 90) |
Example
curl https://linkjolt.io/api/v1/teams/TEAM_ID/goals \
-X POST \
-H "Authorization: Bearer lj_pk_live_your_key" \
-H "Content-Type: application/json" \
-d '{"name":"July revenue push","metric":"revenue","targetValue":10000,"periodMode":"monthly","bonusType":"flat","bonusValue":500,"refundSafeDays":14}'Response
{
"data": {
"id": "goal_2Nw6Vx",
"scope": "team",
"campaignId": null,
"name": "July revenue push",
"metric": "revenue",
"targetValue": "10000",
"periodMode": "monthly",
"bonusType": "flat",
"bonusValue": "500",
"bonusScope": "team",
"bonusSplit": "equal",
"bonusVisibility": "all",
"status": "active",
"refundSafeDays": 14,
"createdAt": "2026-07-15T10:30:00Z"
}
}/api/v1/teams/:id/goals/:goalId
Update Team Goal
Change a goal's lifecycle: cancel it, close its current period now to finalize awards, or reactivate an ended goal. reactivate is optimistic-concurrency guarded: send the goal's current updatedAt as expectedUpdatedAt and get 409 stale_goal if it drifted. The response is lean: { id, status }, plus closedAt when the action was close_now. Editing a goal's targets or reviewing leader proposals stays in the dashboard. Scale plan, live keys only.
Parameters
| id* | string | Team ID (path parameter) |
| goalId* | string | Goal ID (path parameter) |
| action* | string | "cancel", "close_now", or "reactivate" |
| expectedUpdatedAt | string | Required for "reactivate": the goal's current updatedAt (ISO 8601) |
Example
curl https://linkjolt.io/api/v1/teams/TEAM_ID/goals/GOAL_ID \
-X PATCH \
-H "Authorization: Bearer lj_pk_live_your_key" \
-H "Content-Type: application/json" \
-d '{"action":"cancel"}'Response
{
"data": {
"id": "goal_2Nw6Vx",
"status": "cancelled"
}
}/api/v1/teams/:id/awards
List Team Awards
List one team's bonus award ledger, paginated and newest first. Each award moves through pending_window (provisional during the refund-safe window), pending_approval, approved, processing, paid, cancelled, or failed. Scale plan only.
Parameters
| id* | string | Team ID (path parameter) |
| status | string | Filter by award status |
| page | number | Page number |
| limit | number | Results per page (max 100) |
Example
curl "https://linkjolt.io/api/v1/teams/TEAM_ID/awards?status=pending_approval" \
-H "Authorization: Bearer lj_pk_live_your_key"Response
{
"data": [
{
"id": "award_4Jd0Pc",
"goalId": "goal_2Nw6Vx",
"goalName": "July revenue push",
"affiliateId": "aff_5Yh1Qn",
"affiliateName": "Jane Smith",
"affiliateEmail": "jane@example.com",
"amount": "250.00",
"currency": "usd",
"periodKey": "2026-07",
"status": "pending_approval",
"payableAfter": "2026-08-01T00:00:00Z",
"approvedAt": null,
"paidAt": null,
"payoutMethod": null,
"stripeTransferId": null,
"failureReason": null,
"contributing": { "count": 5, "amount": 6250 },
"createdAt": "2026-07-31T23:59:00Z"
}
],
"pagination": { "page": 1, "limit": 25, "total": 8, "totalPages": 1 }
}/api/v1/awards
List All Awards
A brand-wide bonus award ledger across every team, for reconciliation. Filter by status, period, affiliate, or team. Paginated and newest first. Scale plan only.
Parameters
| status | string | Filter by award status |
| periodKey | string | Filter by period (e.g. "2026-07" or "one_time") |
| affiliateId | string | Filter by affiliate |
| teamId | string | Filter by team |
| page | number | Page number |
| limit | number | Results per page (max 100) |
Example
curl "https://linkjolt.io/api/v1/awards?status=paid&periodKey=2026-07" \
-H "Authorization: Bearer lj_pk_live_your_key"Response
{
"data": [
{
"id": "award_9Zs2Bk",
"teamId": "team_7bKq2mZ",
"teamName": "EU Growth Squad",
"goalId": "goal_2Nw6Vx",
"goalName": "July revenue push",
"affiliateId": "aff_5Yh1Qn",
"affiliateName": "Jane Smith",
"amount": "250.00",
"currency": "usd",
"periodKey": "2026-07",
"status": "paid",
"payableAfter": "2026-08-01T00:00:00Z",
"approvedAt": "2026-08-01T09:00:00Z",
"paidAt": "2026-08-02T00:05:00Z",
"payoutMethod": "stripe",
"stripeTransferId": "tr_1PabcXYZ",
"failureReason": null,
"createdAt": "2026-07-31T23:59:00Z"
}
],
"pagination": { "page": 1, "limit": 25, "total": 31, "totalPages": 2 }
}/api/v1/teams/:id/awards/:awardId
Approve or Manage an Award
Move a bonus award through its lifecycle: approve a finalized award (pending_approval to approved, which queues its payout), mark_paid to record a manual payout (approved to paid), or cancel it (from pending_window, pending_approval, or approved). Approving is idempotent: re-sending when the award is already at the target status returns 200 with idempotent:true. This is a money action on the same trust model as approving a commission with PATCH /conversions/:id: any write key can do it, and the approver is stamped as apikey:<keyId>. Scale plan, live keys only.
Parameters
| id* | string | Team ID (path parameter) |
| awardId* | string | Award ID (path parameter) |
| action* | string | "approve", "mark_paid", or "cancel" |
Example
curl https://linkjolt.io/api/v1/teams/TEAM_ID/awards/AWARD_ID \
-X PATCH \
-H "Authorization: Bearer lj_pk_live_your_key" \
-H "Content-Type: application/json" \
-d '{"action":"approve"}'Response
{
"data": {
"id": "award_4Jd0Pc",
"goalId": "goal_2Nw6Vx",
"teamId": "team_7bKq2mZ",
"teamName": "EU Growth Squad",
"affiliateId": "aff_5Yh1Qn",
"amount": "250.00",
"currency": "usd",
"periodKey": "2026-07",
"status": "approved",
"approvedAt": "2026-08-01T09:00:00Z",
"approvedBy": "apikey:k_9Fk2Lp",
"updatedAt": "2026-08-01T09:00:00Z"
}
}/api/v1/teams/:id/history
Get Team History
Past goal results by period for a team: for each period, every goal's target, achieved amount, whether it was hit, percent to target, per-member contributions, any currency-excluded amounts, and the period's total payouts. Newest period first. Scale plan only.
Parameters
| id* | string | Team ID (path parameter) |
| months | number | How many months back to include (default: 6) |
Example
curl "https://linkjolt.io/api/v1/teams/TEAM_ID/history?months=6" \
-H "Authorization: Bearer lj_pk_live_your_key"Response
{
"data": {
"currency": "usd",
"months": 6,
"periods": [
{
"periodKey": "2026-07",
"goals": [
{
"goalId": "goal_2Nw6Vx",
"name": "July revenue push",
"metric": "revenue",
"scope": "team",
"campaignId": null,
"periodMode": "monthly",
"status": "ended",
"target": 10000,
"achieved": 11200,
"hit": true,
"pct": 100,
"members": [
{ "affiliateId": "aff_5Yh1Qn", "name": "Jane Smith", "email": "jane@example.com", "contribution": 7000 },
{ "affiliateId": "aff_8Rt3Wm", "name": "Marco Rossi", "email": "marco@example.com", "contribution": 4200 }
],
"excludedByCurrency": {}
}
],
"payoutTotal": 500,
"payoutCount": 2
}
]
}
}Register the discount codes your affiliates promote so LinkJolt can attribute coupon-based sales. Reads work on any valid key (Pro and up); writes need an Ultimate or Scale write key, the same tiers as conversions. Test keys tag new coupons as test data and see only test coupons.
/api/v1/coupons
List Coupons
List the affiliate coupon codes registered on your brand, with the campaign and affiliate each is attributed to. Filter by campaign, affiliate, provider, or code. Reads work on any valid key (Pro and up). Test keys see only test coupons.
Parameters
| campaignId | string | Filter by campaign ID |
| affiliateId | string | Filter by affiliate ID |
| provider | string | Filter: stripe, paddle, or apple |
| code | string | Filter by exact coupon code |
| page | number | Page number |
| limit | number | Results per page (max 100) |
Example
curl "https://linkjolt.io/api/v1/coupons?campaignId=camp_9Fk2Lp" \
-H "Authorization: Bearer lj_pk_your_key"Response
{
"data": [
{
"id": "cpn_8Lz3Rk",
"code": "JANE20",
"provider": "stripe",
"campaignId": "camp_9Fk2Lp",
"campaignName": "Summer Launch",
"affiliateId": "aff_5Yh1Qn",
"stripePromotionCodeId": "promo_1Pabc123",
"paddleDiscountId": null,
"appleOfferType": null,
"percentOff": "20",
"amountOff": null,
"currency": null,
"isTest": false,
"createdAt": "2026-06-01T10:00:00Z"
}
],
"pagination": { "page": 1, "limit": 25, "total": 6, "totalPages": 1 }
}/api/v1/coupons
Register a Coupon
Register a discount code so LinkJolt attributes coupon-based sales to an affiliate. LinkJolt does not create the code in Stripe, Paddle, or the App Store; you create it there and register the reference here. The affiliate must have an approved relationship with your brand. Codes are stored uppercase for stripe and paddle and case-sensitive for apple. Registering a code that already exists for the same campaign, provider, and mode returns 409 coupon_exists. Requires an Ultimate or Scale write key.
Parameters
| campaignId* | string | Campaign the coupon belongs to (your brand) |
| affiliateId* | string | Affiliate to attribute the coupon to (approved on your brand) |
| code* | string | The discount code as customers enter it |
| provider | string | "stripe" (default), "paddle", or "apple" |
| stripePromotionCodeId | string | Stripe promotion code id (must start with "promo_"); stripe only |
| paddleDiscountId | string | Paddle discount id; paddle only |
| appleOfferType | number | 1 introductory, 2 promotional, or 3 offer code; apple only |
| percentOff | number | Display-only discount percent |
| amountOff | number | Display-only discount amount |
| currency | string | Display-only currency for amountOff |
Example
curl https://linkjolt.io/api/v1/coupons \
-X POST \
-H "Authorization: Bearer lj_pk_your_key" \
-H "Content-Type: application/json" \
-d '{"campaignId":"camp_9Fk2Lp","affiliateId":"aff_5Yh1Qn","code":"JANE20","provider":"stripe","stripePromotionCodeId":"promo_1Pabc123","percentOff":20}'Response
{
"data": {
"id": "cpn_8Lz3Rk",
"code": "JANE20",
"provider": "stripe",
"campaignId": "camp_9Fk2Lp",
"affiliateId": "aff_5Yh1Qn",
"stripePromotionCodeId": "promo_1Pabc123",
"paddleDiscountId": null,
"appleOfferType": null,
"percentOff": "20",
"amountOff": null,
"currency": null,
"isTest": false,
"createdAt": "2026-07-15T10:30:00Z"
}
}/api/v1/coupons/:id
Get, Update, or Delete a Coupon
GET returns one coupon (any valid key, Pro and up). PATCH updates only the provider match id for the coupon's provider: stripePromotionCodeId for stripe, paddleDiscountId for paddle; apple coupons have no editable fields. DELETE removes the coupon (it stops attributing new sales; past conversions are unchanged). PATCH and DELETE require an Ultimate or Scale write key. All operations are scoped to your brand.
Parameters
| id* | string | Coupon ID (path parameter) |
| stripePromotionCodeId | string | (PATCH, stripe) new promotion code id, must start with "promo_" |
| paddleDiscountId | string | (PATCH, paddle) new Paddle discount id |
Example
# Get one coupon
curl https://linkjolt.io/api/v1/coupons/COUPON_ID \
-H "Authorization: Bearer lj_pk_your_key"
# Update the Stripe promotion code id
curl https://linkjolt.io/api/v1/coupons/COUPON_ID \
-X PATCH \
-H "Authorization: Bearer lj_pk_your_key" \
-H "Content-Type: application/json" \
-d '{"stripePromotionCodeId":"promo_1Pxyz789"}'
# Delete a coupon
curl https://linkjolt.io/api/v1/coupons/COUPON_ID \
-X DELETE \
-H "Authorization: Bearer lj_pk_your_key"Response
{
"data": {
"id": "cpn_8Lz3Rk",
"code": "JANE20",
"provider": "stripe",
"campaignId": "camp_9Fk2Lp",
"campaignName": "Summer Launch",
"affiliateId": "aff_5Yh1Qn",
"stripePromotionCodeId": "promo_1Pabc123",
"paddleDiscountId": null,
"appleOfferType": null,
"percentOff": "20",
"amountOff": null,
"currency": null,
"isTest": false,
"createdAt": "2026-06-01T10:00:00Z"
}
}Read-only visibility into your affiliate payout queue for finance reconciliation. Available on any valid key (Pro and up).
/api/v1/payouts
List Payouts
Read-only visibility into your affiliate payout queue for finance reconciliation. Each row is a queued or completed commission payout with its status, schedule, attempt history, and (for Stripe Connect payouts) the Stripe payment id. Filter by status, affiliate, conversion, or date range. Available on any valid key (Pro and up).
Parameters
| status | string | Filter: pending, awaiting_funds, scheduled, processing, completed, failed |
| affiliateId | string | Filter by affiliate ID |
| conversionId | string | Filter by the source conversion ID |
| from | date | Start date (ISO 8601), filters on scheduledDate |
| to | date | End date (ISO 8601) |
| page | number | Page number |
| limit | number | Results per page (max 100) |
Example
curl "https://linkjolt.io/api/v1/payouts?status=completed&from=2026-07-01" \
-H "Authorization: Bearer lj_pk_your_key"Response
{
"data": [
{
"id": "pay_6Ht9Bs",
"conversionId": "conv_1Ab2Cd",
"campaignId": "camp_9Fk2Lp",
"affiliateId": "aff_5Yh1Qn",
"amount": "20.00",
"currency": "usd",
"status": "completed",
"scheduledDate": "2026-07-10T00:00:00Z",
"attempts": 1,
"lastAttemptAt": "2026-07-10T00:05:00Z",
"completedAt": "2026-07-10T00:05:03Z",
"stripePaymentId": "tr_1Pabc456",
"failureReason": null,
"createdAt": "2026-07-09T12:00:00Z"
}
],
"pagination": { "page": 1, "limit": 25, "total": 18, "totalPages": 1 }
}/api/v1/me
Verify API Key
Lightweight ping endpoint to verify your API key works. Returns your merchant info, key permissions, plan, and current rate limit status.
Example
curl https://linkjolt.io/api/v1/me \
-H "Authorization: Bearer lj_pk_your_key"Response
{
"data": {
"merchant": { "id": "m_abc", "businessName": "Acme Inc", "email": "team@acme.com" },
"apiKey": { "id": "k_123", "name": "Production", "permissions": { "read": true, "write": false }, "keyType": "live" },
"plan": "professional",
"rateLimit": { "limit": 60, "remaining": 59, "resetAt": 1713100860 }
}
}/api/v1/stats
Get Stats
Returns aggregate statistics: total revenue, commissions, conversions, and affiliate count for a date range.
Parameters
| from | date | Start date (default: first of current month) |
| to | date | End date (default: now) |
Example
curl "https://linkjolt.io/api/v1/stats?from=2026-04-01" \
-H "Authorization: Bearer lj_pk_your_key"Response
{
"data": {
"totalRevenue": 12350.00,
"totalTax": 0.00,
"totalCommissions": 2470.00,
"totalConversions": 47,
"totalClicks": 1820,
"totalAffiliates": 12,
"periodStart": "2026-04-01T00:00:00Z",
"periodEnd": "2026-04-13T23:59:59Z"
}
}/api/v1/stats/overview
Program Overview
Current-calendar-month snapshot in one call: revenue, commissions, conversion count, top 5 affiliates by commission, and the 10 most recent conversions. Powers the MCP get_program_overview tool and its interactive card in Claude.
Example
curl https://linkjolt.io/api/v1/stats/overview \
-H "Authorization: Bearer lj_pk_your_key"Response
{
"data": {
"period": { "from": "2026-08-01T00:00:00.000Z", "to": "2026-08-26T10:00:00.000Z" },
"currency": "USD",
"revenue": 12350.00,
"commissions": 2470.00,
"conversionsCount": 47,
"topAffiliates": [
{ "affiliateId": "aff_123", "name": "Sarah Chen", "commission": 840.00, "conversions": 14 }
],
"recentConversions": [
{ "id": "conv_9", "orderId": "ord_551", "customerName": "Alex Doyle", "amount": 250.00, "commission": 50.00, "currency": "USD", "status": "approved", "createdAt": "2026-08-25T18:40:00.000Z" }
]
}
}/api/v1/search
Search
Brand-scoped free-text search across campaigns, affiliates, coupon codes, and conversions (order id, customer name or email). Returns thin results with composite ids (campaign:<id>, affiliate:<id>, coupon:<id>, conversion:<id>) that resolve through the matching GET-by-id endpoints. Powers the MCP search and fetch tools for ChatGPT Company knowledge and Deep Research.
Parameters
| q* | string | Search text, at least 2 characters |
| limit | number | Max results per category (default 5, max 20) |
Example
curl "https://linkjolt.io/api/v1/search?q=sarah" \
-H "Authorization: Bearer lj_pk_your_key"Response
{
"data": {
"results": [
{ "id": "campaign:camp_abc", "title": "Pro Plan Launch (active campaign)", "url": "https://www.linkjolt.io/merchant/campaigns", "type": "campaign" },
{ "id": "affiliate:aff_123", "title": "Sarah Chen (sarah@techreviews.com)", "url": "https://www.linkjolt.io/merchant/affiliates", "type": "affiliate" },
{ "id": "conversion:conv_9", "title": "Order ord_551 from Alex Doyle (approved)", "url": "https://www.linkjolt.io/merchant/commissions", "type": "conversion" }
]
}
}/api/v1/webhooks
Manage Webhooks
Manage outbound webhook subscriptions. GET lists all, POST creates a new one, DELETE deactivates one. PATCH /api/v1/webhooks/:id updates url/events or re-enables a paused subscription (active: true, resets the failure count). GET /api/v1/webhooks/:id/deliveries lists recent delivery attempts.
Parameters
| url* | string | (POST) HTTPS URL to deliver events to |
| events* | string[] | (POST) e.g. ["conversion.created","payout.completed"] |
| active | boolean | (PATCH /:id) true re-enables a paused subscription and resets its failure count |
Example
# Create
curl https://linkjolt.io/api/v1/webhooks \
-X POST \
-H "Authorization: Bearer lj_pk_your_key" \
-H "Content-Type: application/json" \
-d '{"url":"https://yourapp.com/hooks","events":["conversion.created"]}'
# List
curl https://linkjolt.io/api/v1/webhooks \
-H "Authorization: Bearer lj_pk_your_key"
# Re-enable a paused subscription (resets failure count)
curl https://linkjolt.io/api/v1/webhooks/WEBHOOK_ID \
-X PATCH \
-H "Authorization: Bearer lj_pk_your_key" \
-H "Content-Type: application/json" \
-d '{"active":true}'
# Recent delivery attempts (?limit= up to 100)
curl https://linkjolt.io/api/v1/webhooks/WEBHOOK_ID/deliveries \
-H "Authorization: Bearer lj_pk_your_key"Response
// POST response: secret shown ONCE
{
"data": {
"id": "wh_abc",
"url": "https://yourapp.com/webhooks/linkjolt",
"events": ["conversion.created", "payout.completed"],
"secret": "hex_32_bytes...",
"active": true,
"createdAt": "..."
}
}/api/v1/webhooks/:id/rotate
Rotate Webhook Secret
Generate a new signing secret for a webhook. Old secret stops working immediately. Returns new secret once.
Parameters
| id* | string | Webhook subscription ID (path parameter) |
Example
curl https://linkjolt.io/api/v1/webhooks/WEBHOOK_ID/rotate \
-X POST \
-H "Authorization: Bearer lj_pk_your_key"Response
{
"data": {
"id": "wh_abc",
"secret": "new_hex_secret...",
"message": "Secret rotated. Update your webhook verification code with this new secret."
}
}/api/v1/webhooks/:id/test
Test Webhook
Send a signed "ping" event to the webhook URL. Returns the HTTP status and response body so you can verify your endpoint works.
Parameters
| id* | string | Webhook subscription ID (path parameter) |
Example
curl https://linkjolt.io/api/v1/webhooks/WEBHOOK_ID/test \
-X POST \
-H "Authorization: Bearer lj_pk_your_key"Response
{
"data": {
"success": true,
"httpStatus": 200,
"responseBody": "OK",
"url": "https://yourapp.com/webhooks/linkjolt"
}
}Conventions
sort (e.g. ?sort=createdAt:desc) and page/limit.X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, and X-API-Version headers.{ error: { code, message, details? } }Retry-After.