API Documentation
Getting started
Base URL: https://affi.link/api/v1
Every request needs an Authorization: Bearer <token> header and an Accept: application/json header (so errors come back as JSON instead of HTML).
Create a token on the API Tokens page — the abilities you check there (create, read, update, delete) map 1:1 onto the HTTP verbs below.
curl https://affi.link/api/v1/links \
-H "Authorization: Bearer <token>" \
-H "Accept: application/json"
Endpoints
GET /links (ability: read)
List your links. Query params: sort, direction, category_id, search, per_page (max 100).
{
"data": [
{
"id": 42,
"short_code": "EdRbko",
"short_url": "https://go.affi.link/EdRbko",
"redirect_url": "https://example.com/product",
"type": "simple",
"is_active": true,
"click_count": 16,
"category": {"id": 3, "name": "Kitchen"},
"domain": null
}
],
"links": {"first": "...", "last": "...", "next": null},
"meta": {"current_page": 1, "per_page": 15, "total": 1}
}
POST /links (ability: create)
Create a link. Body: redirect_url (required), category_id (optional), conditions (optional array of targeting rules — same fields as the "Advanced options" form on the web dashboard; Business plan only).
curl -X POST https://affi.link/api/v1/links \
-H "Authorization: Bearer <token>" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"redirect_url": "https://example.com/product"}'
GET /links/{id} (ability: read)
Get a single link, including its targeting conditions.
PATCH /links/{id} (ability: update)
Update a link. Body: is_active and/or category_id — only send the fields you want to change.
DELETE /links/{id} (ability: delete)
Delete a link. Returns 204 No Content on success.
GET /links/{id}/stats (ability: read)
Total clicks and clicks this month, on every plan. trend and ?with=country,device,browser,os breakdowns require Business plan only.
POST /links/bulk (ability: create) Business plan only
Create up to 100 links in one call. Each item is validated independently — one bad item doesn't fail the batch.
{
"created": [ {"id": 42, "short_code": "...", ...} ],
"errors": [ {"index": 2, "message": "The redirect url field is required."} ]
}
GET /links/{id}/landing-options, PUT, DELETE Business plan only
Manage a link's "Choice Page" (multiple destinations, visitor picks one). PUT body: {"options": ["url1", "url2", ...]} (2–8 URLs) — replaces the full set, so resend the complete list to add, reorder, or remove an option. DELETE turns the link back into a normal single-destination link.
Affiliate tags Business plan only
Manage the affiliate tags used to build your own links for each retailer program.
- GET
/affiliates(ability: read) — list your tags. - POST
/affiliates(ability: create) — body:affiliate_program_id,tag. - PATCH
/affiliates/{id}(ability: update) — body:tag. - DELETE
/affiliates/{id}(ability: delete).
Custom domains Business plan only
Manage your branded domains. These endpoints call AWS directly and have their own stricter limit
(10 requests/minute, separate from your plan's general rate limit) — avoid polling check in a tight loop.
- GET
/domains(ability: read). - POST
/domains(ability: create) — body:hostname. - POST
/domains/{id}/check(ability: update) — poll validation status. - DELETE
/domains/{id}(ability: delete).
Errors
| Status | Meaning |
|---|---|
| 422 | Validation failed — see errors in the response body. |
| 403 | Plan doesn't include API access (or doesn't include Business-only access to this endpoint), token is missing the required ability, or the resource isn't yours. |
| 404 | Resource not found. |
| 429 | Rate limit exceeded — see the Retry-After header. Custom domain endpoints have their own separate, stricter limit. |