Building a custom store integration?
Start with the universal integration guide. It explains the click identifier, store-side script and backend postback.
Open universal integrationUsing WooCommerce?
Use the dedicated plugin and webhook guide for WooCommerce orders and statuses.
Open WooCommerce documentationOverview
Linkolino API covers click tracking, conversion registration and webhook-based integrations. Affiliate clicks are tracked through `/r/:code`, while sales should be reported from the store backend.
Authentication
API requests require an API key. Use the `X-Api-Key` header for server-side requests. Query parameter authentication is supported only for simple compatibility scenarios.
Recommended header
curl -H "X-Api-Key: YOUR_API_KEY" \
https://app.linkolino.pl/api/postback/PROGRAM_ID?order_id=123&amount=99.99
If you rotate the API key in the merchant panel, the previous key stops working immediately. Update your store backend before sending the next postback.
1. Click tracking
Clicks are registered automatically when a user opens an affiliate link. Linkolino stores the click and redirects the customer to the target URL.
https://app.linkolino.pl/r/abc123def
Use `sub_id`, `sub_id_2` and `sub_id_3` when you want to pass campaign or placement markers.
2. Conversion registration
After a transaction, send a postback from your backend to register a conversion and calculate affiliate commission.
GET /api/postback/:program_id\nPOST /api/postback/:program_id
| Parameter | Type/limit | Required/window | Description |
|---|---|---|---|
| order_id | string | yes | Unique order identifier in your system. |
| amount | decimal | yes | Order value, for example `199.99`. |
| visitor_id | string | recommended | Visitor identifier stored from the affiliate click. |
| currency | string | no | Currency code, `PLN` by default. |
| customer_id | string | no | Internal customer ID or hash. |
| sub_id | string | no | Optional campaign marker. |
GET
curl -H "X-Api-Key: sk_live_abc123" \
"https://app.linkolino.pl/api/postback/PROGRAM_ID?order_id=ORD-001&amount=299.99"
POST JSON
curl -X POST \
-H "X-Api-Key: sk_live_abc123" \
-H "Content-Type: application/json" \
-d '{"order_id":"ORD-001","amount":299.99,"visitor_id":"VISITOR_ID"}' \
"https://app.linkolino.pl/api/postback/PROGRAM_ID"
Success response
{
"success": true,
"conversion_id": "550e8400-e29b-41d4-...",
"status": "pending"
}
Canonical conversion payload
All integrations should map order data to one shared conversion contract. The minimal payload needs `program_id`, `order_id`, `currency`, one identity field (`visitor_id` or `click_id`) and one amount field (`gross_amount`, `net_amount`, `items_amount` or the legacy `amount`).
{
"program_id": "PROGRAM_ID",
"order_id": "ORD-001",
"visitor_id": "VISITOR_ID",
"click_id": null,
"customer_id_hash": "sha256(customer-id)",
"gross_amount": "246.00",
"net_amount": "200.00",
"items_amount": "220.00",
"shipping_amount": "20.00",
"discount_amount": "10.00",
"tax_amount": "46.00",
"currency": "PLN",
"order_status": "completed",
"payment_status": "paid",
"refunded_amount": "0.00",
"consent_mode": "merchant_consent_required",
"integration_mode": "plugin",
"source": "woocommerce"
}
`customer_id_hash` can be useful for deduplication, but it should be a hash or internal pseudonymous identifier. Do not send names, emails, phone numbers or delivery addresses in conversion payloads unless a separate legal basis and data-processing agreement require it.
Supported consent modes are `merchant_consent_required`, `server_side_required` and `custom`. The merchant remains responsible for CMP configuration, cookie consent and privacy notices in the store.
3. Platform integrations
WooCommerce
Use the WordPress plugin or webhook-only mode when order metadata already contains `visitor_id`.
Shopify
The recommended path is a Shopify app with OAuth, webhooks and customer-event tracking.
Stripe
Pass `visitor_id` and `program_id` in Checkout Session metadata.
Custom stores
Use the universal script plus backend postback flow.
Stripe Checkout Session
const session = await stripe.checkout.sessions.create({
// ... other parameters
metadata: {
visitor_id: req.cookies._mm_track || '',
program_id: 'YOUR_PROGRAM_ID'
}
});
4. Limits and errors
| Parameter | Type/limit | Required/window | Description |
|---|---|---|---|
| /r/:code | 30/IP | 1 min | Affiliate redirect rate limit. |
| /api/postback/:id | 100/IP + program | 1 min | Postback rate limit. |
After exceeding a limit, the API returns `429 Too Many Requests`.