Agent Integration
Base URL: https://api.syndicatelinks.co
All examples use production base URL. Replace with http://localhost:3000 for local testing.
Authentication
Two key types for agents:
aff_agent_— issued to autonomous agents and agent platforms. Use for machine-to-machine calls.ak_live_/aff_human_— human affiliate keys. Agents should not use these.
Header:
Authorization: Bearer aff_agent_...
Scope vocabulary
merchant:*— full merchant operations (register, programs, products, reports)affiliate:*— affiliate operations (links, events, payouts, analytics)agent:*— agent-specific attribution and commission endpoints
Request an aff_agent_ key via POST /affiliate/register with type=agent.
Cold merchant registration
Agents can onboard merchants programmatically. The /merchant/register endpoint requires no auth.
curl
curl -X POST https://api.syndicatelinks.co/merchant/register \
-H "Content-Type: application/json" \
-d '{
"name": "Acme Store",
"email": "[email protected]",
"website": "https://acme.example",
"description": "Handcrafted tools",
"category": "tools"
}'
TypeScript (fetch)
const res = await fetch("https://api.syndicatelinks.co/merchant/register", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
name: "Acme Store",
email: "[email protected]",
website: "https://acme.example",
}),
});
const { id, apiKey, slug } = await res.json();
Python (httpx)
import httpx
async def register_merchant():
async with httpx.AsyncClient() as client:
r = await client.post(
"https://api.syndicatelinks.co/merchant/register",
json={
"name": "Acme Store",
"email": "[email protected]",
"website": "https://acme.example",
},
)
data = r.json()
return data["id"], data["apiKey"], data["slug"]
Response shape
{
"id": "uuid",
"name": "Acme Store",
"email": "[email protected]",
"slug": "acme-store",
"apiKey": "mk_live_..."
}
The apiKey is returned once. Store it securely.
Program creation
Requires merchant key (mk_live_).
curl
curl -X POST https://api.syndicatelinks.co/merchant/programs \
-H "Authorization: Bearer mk_live_..." \
-H "Content-Type: application/json" \
-d '{
"name": "Acme Affiliate Program",
"commissionPct": 15,
"cookieDays": 30
}'
TypeScript / Python examples follow the same pattern as registration — replace endpoint and auth header.
Product import
Single product
POST /merchant/products
Request
{
"programId": "uuid",
"name": "Hammer",
"url": "https://acme.example/hammer",
"price": "29.99",
"externalId": "hammer-001",
"commissionPct": 15
}
Bulk import
POST /merchant/products/bulk
{
"programId": "uuid",
"products": [
{ "name": "Hammer", "url": "...", "price": "29.99", ... },
{ "name": "Saw", "url": "...", "price": "49.99", ... }
]
}
Response
{ "inserted": 42 }
Tracking link generation
Two scopes:
- code-scoped — uses a human-readable tracking code
- merchant-scoped — uses program + merchant context only
Endpoint: POST /affiliate/links
Request (code-scoped)
{
"programId": "uuid",
"trackingCode": "acme-hammer-referral",
"destinationUrl": "https://acme.example/hammer"
}
Response
{
"id": "uuid",
"shortUrl": "https://sl.link/abc123",
"trackingCode": "acme-hammer-referral"
}
Conversion firing
Direct POST
POST /affiliate/events/conversion
{
"linkId": "uuid",
"orderId": "order-12345",
"saleAmount": "99.00",
"attributionMethod": "agent_token",
"referrerContext": {
"agent_id": "agent-uuid",
"surface": "claude-desktop",
"query": "best hammer for framing"
}
}
Webhook receiver pattern
Merchants configure webhooks at POST /merchant/webhooks.
Payload signature: X-SL-Signature header (HMAC-SHA256 of body with webhook secret).
Example receiver (Node)
app.post("/webhook/sl", (req, res) => {
const sig = req.headers["x-sl-signature"];
const valid = verifyHmac(req.body, secret, sig);
if (!valid) return res.status(401).send("bad sig");
const { event, data } = req.body;
if (event === "conversion") {
// credit agent
}
res.sendStatus(200);
});
Retry behavior: 5 attempts, exponential backoff, 24h max.
Webhook configuration
Event types
conversionclickpayoutmerchant.created
Signing
All webhooks include X-SL-Signature. Verify before processing.
Analytics pulls
GET /affiliate/analytics/conversions?from=2026-05-01&to=2026-06-01&cursor=...&limit=50
Response
{
"data": [ /* ConversionEvent */ ],
"cursor": "uuid | null",
"hasMore": true
}
Rate limit: 120 requests per minute per key. Exceeding returns 429.
Full worked example
Reference agent that:
- Registers merchant (if cold)
- Creates program
- Imports products
- Generates tracking link
- Fires conversion on purchase
- Pulls analytics
See examples/agent-integration.ts in the SDK for complete runnable code.
Attribution skill pack
If your agent runtime supports portable skills, install the public Syndicate Links attribution pack before building the flow from scratch:
npx skills add syndicatelinks/attribution-skills
Repository: github.com/syndicatelinks/attribution-skills
The pack gives agents ready-made procedures for attribution install, agent-key issuance, and conversion testing against the authenticated Syndicate Links API. Use it alongside this API contract when you want the workflow scaffolded inside the agent rather than handwritten in application code.
Error handling + rate limits
All errors:
{ "error": "Human-readable message" }
Common codes:
- 400 — validation
- 401 — bad key
- 403 — wrong key type or ownership
- 404 — not found
- 409 — conflict
- 429 — rate limit
Always retry on 5xx with jitter. Do not retry 4xx except 429 (respect Retry-After).
Machine-parseable sections above are the contract. Any implementation must match the request/response shapes exactly.