Introduction

The Eastlink API gives enterprise customers programmatic access to campaigns, conversions, affiliates, analytics, and webhooks. Use it to integrate affiliate tracking directly into your existing CRM, e-commerce platform, or booking system.

Base URL https://api.eastlink.africa/v1
All API requests must be made over HTTPS. HTTP requests will be rejected. All response bodies are JSON.

Response Format

Every response follows a consistent envelope:

{
  "success": true,
  "data": { ... },
  "meta": {
    "timestamp": "2026-04-25T10:30:00.000Z",
    "version": "v1",
    "total": 150,
    "page": 1,
    "limit": 20
  }
}

Error responses use the same envelope with success: false:

{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "saleValue is required for sale conversions"
  },
  "meta": {
    "timestamp": "2026-04-25T10:30:00.000Z",
    "version": "v1"
  }
}

Authentication

All API requests must include your API key in the X-API-Key request header. Generate and manage your keys on the API Keys page.

Never expose your API key in client-side code, browser JavaScript, or mobile apps. Keys should only be used from your server-side backend.

Example Request

curl https://api.eastlink.africa/v1/campaigns \
  -H "X-API-Key: elk_live_your_key_here"
const response = await fetch('https://api.eastlink.africa/v1/campaigns', {
  headers: { 'X-API-Key': 'elk_live_your_key_here' }
});
const { data } = await response.json();

API Key Scopes

ScopeAccess
campaigns:readRead campaign data
conversions:readRead conversion records
conversions:writeRecord new conversions and confirm/reject them
affiliates:readRead affiliate data
analytics:readAccess analytics data
products:readRead product catalog

Rate Limits

The API enforces a rate limit of 100 requests per minute per API key. If you exceed this, you will receive a 429 Too Many Requests response.

Rate limit windows reset every 60 seconds. For high-volume integrations such as batch processing, use bulk operations and cache responses where possible.

Error Codes

HTTP StatusCodeDescription
400VALIDATION_ERRORRequest body is missing required fields or has invalid values
401MISSING_API_KEYX-API-Key header is absent
401INVALID_API_KEYAPI key is invalid, revoked, or does not exist
403FORBIDDENAuthenticated but not authorized to access this resource
403INSUFFICIENT_SCOPEKey lacks the required scope for this operation
403IP_NOT_WHITELISTEDRequest IP is not in the key's IP whitelist
404NOT_FOUNDRequested resource does not exist
409DUPLICATE_ORDERConversion with this orderId already exists (deduplication)
422VALIDATION_ERRORSemantically invalid — fields present but fail validation rules
429RATE_LIMIT_EXCEEDEDExceeded 100 requests per minute
500INTERNAL_ERRORServer error — contact support if persistent

Campaigns

GET /v1/campaigns Scope: campaigns:read

Returns all campaigns belonging to the authenticated merchant, ordered by creation date descending.

Query Parameters

ParameterTypeDescription
pageintegerPage number (default: 1)
limitintegerResults per page, max 100 (default: 20)

Response

{
  "success": true,
  "data": {
    "campaigns": [
      {
        "id": "camp_abc123",
        "name": "Kenya Hotel Referral Program",
        "status": "active",
        "type": "open",
        "commissionRate": 10,
        "commissionType": "percentage",
        "cookieDuration": 30,
        "productsCount": 3,
        "affiliatesCount": 47,
        "countries": ["KE", "TZ", "UG"],
        "channels": ["social", "blog"],
        "createdAt": "2026-01-15T08:30:00.000Z"
      }
    ]
  },
  "meta": { "total": 5, "page": 1, "limit": 20, "pages": 1 }
}
GET /v1/campaigns/:campaignId Scope: campaigns:read

Returns full details for a single campaign including its products array.

{
  "success": true,
  "data": {
    "id": "camp_abc123",
    "name": "Kenya Hotel Referral Program",
    "description": "Refer travellers to our Nairobi properties",
    "status": "active",
    "type": "open",
    "commissionStructure": { "type": "percentage", "value": 10 },
    "cookieDuration": 30,
    "payoutHoldDays": 7,
    "countries": ["KE", "TZ"],
    "channels": ["social", "email"],
    "multiTierEnabled": false,
    "products": [
      {
        "id": "prod_xyz",
        "name": "Nairobi Hilton — Standard Room",
        "type": "booking",
        "price": 150,
        "currency": "USD",
        "commissionType": "percentage",
        "commissionValue": 10,
        "status": "active"
      }
    ],
    "createdAt": "2026-01-15T08:30:00.000Z",
    "updatedAt": "2026-03-01T12:00:00.000Z"
  }
}

Conversions

Conversions represent completed actions — sales, leads, bookings, or applications — referred by an affiliate. Recording conversions via the API is the most important integration for enterprise customers.

POST /v1/conversions Scope: conversions:write

Records a conversion. Eastlink validates the affiliate, calculates commission, deducts from merchant wallet, and credits the affiliate balance atomically.

Request Body

FieldTypeRequiredDescription
campaignIdstringrequiredID of the campaign
affiliateIdstringrequiredID of the referring affiliate
conversionTypestringrequiredsale | lead | booking | application
saleValuenumberrequired for saleTransaction value in the specified currency
currencystringoptionalISO 4217 currency code (default: USD)
orderIdstringoptionalYour unique order ID — used for deduplication
customerEmailstringoptionalCustomer email address
customerPhonestringoptionalCustomer phone number
metadataobjectoptionalAny additional key-value data you want to attach

Example Request

curl -X POST https://api.eastlink.africa/v1/conversions \
  -H "X-API-Key: elk_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "campaignId":     "camp_abc123",
    "affiliateId":    "aff_xyz789",
    "conversionType": "sale",
    "saleValue":      250.00,
    "currency":       "USD",
    "orderId":        "ORDER-98765",
    "customerEmail":  "customer@example.com",
    "metadata": {
      "product": "Safari Package",
      "nights": 3
    }
  }'

Response

{
  "success": true,
  "data": {
    "conversionId":      "conv_Kd8Xp2m",
    "commissionAmount":  25.00,
    "platformFee":       1.50,
    "affiliateReceives": 23.50,
    "status":            "pending"
  },
  "meta": { "timestamp": "2026-04-25T10:30:00.000Z", "version": "v1" }
}
The orderId field enables idempotent deduplication — submitting the same orderId twice returns a 409 DUPLICATE_ORDER error rather than creating a duplicate conversion.
GET /v1/conversions Scope: conversions:read

Returns a paginated list of conversions for the authenticated merchant.

Query Parameters

ParameterTypeDescription
statusstringFilter by: pending | approved | rejected
campaignIdstringFilter to a specific campaign
fromstringISO date string — filter createdAt >= this date
tostringISO date string — filter createdAt <= this date
pageintegerPage number (default: 1)
limitintegerMax 100 results (default: 50)
GET /v1/conversions/:conversionId Scope: conversions:read

Returns full details for a single conversion, including rejection reason and timestamps.

PUT /v1/conversions/:conversionId/confirm Scope: conversions:write

Approve or reject a pending conversion. Approving moves the affiliate's pending balance to available. Rejecting refunds the commission back to the merchant wallet.

Request Body

FieldTypeRequiredDescription
confirmedbooleanrequiredtrue to approve, false to reject
reasonstringoptionalRejection reason (only used when confirmed is false)
curl -X PUT https://api.eastlink.africa/v1/conversions/conv_Kd8Xp2m/confirm \
  -H "X-API-Key: elk_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{ "confirmed": false, "reason": "Order was refunded by customer" }'

Affiliates

GET /v1/affiliates Scope: affiliates:read

Returns all affiliates approved for the merchant's campaigns, with per-affiliate performance stats.

Query Parameters

ParameterTypeDescription
campaignIdstringFilter to affiliates in a specific campaign
statusstringapproved (default) | pending | rejected
page / limitintegerPagination

Response

{
  "success": true,
  "data": {
    "affiliates": [
      {
        "affiliateId":      "aff_xyz789",
        "name":             "Amina Hassan",
        "country":          "TZ",
        "trustLevel":       "premium",
        "totalClicks":      1204,
        "totalConversions": 87,
        "totalEarnings":    1042.50,
        "campaignId":       "camp_abc123",
        "campaignName":     "Kenya Hotel Referral Program",
        "status":           "approved",
        "joinedAt":         "2026-02-10T09:00:00.000Z"
      }
    ]
  },
  "meta": { "total": 47, "page": 1, "limit": 50 }
}

Analytics

GET /v1/analytics Scope: analytics:read

Returns aggregated performance metrics for the merchant across a date range. Defaults to the last 30 days.

Query Parameters

ParameterTypeDescription
fromstringStart date (ISO format, e.g. 2026-01-01)
tostringEnd date (ISO format)
{
  "success": true,
  "data": {
    "clicks": 12400,
    "conversions": 347,
    "conversionRate": 2.80,
    "revenue": 87500.00,
    "commissionPaid": 8750.00,
    "topAffiliates": [
      { "id": "aff_xyz789", "name": "Amina Hassan", "conversions": 87, "earnings": 1042.50 }
    ],
    "topProducts": [
      { "id": "prod_xyz", "name": "Nairobi Hilton", "conversions": 120, "revenue": 18000.00 }
    ],
    "byCountry": [
      { "country": "KE", "clicks": 5200, "conversions": 180 },
      { "country": "TZ", "clicks": 4100, "conversions": 120 }
    ],
    "byDay": [
      { "date": "2026-04-01", "clicks": 420, "conversions": 12 }
    ]
  }
}

Products

GET /v1/products Scope: products:read

Returns all active products in the merchant's catalog. Useful for building affiliate-facing product listings or syncing your catalog.

Webhooks

Webhooks deliver real-time notifications to your server when events occur on the platform. Configure your webhook URL and signing secret on the API Keys page.

Event Types

EventDescription
conversion.createdA new conversion has been recorded (pending approval)
conversion.confirmedA conversion has been approved and commission released
conversion.rejectedA conversion was rejected and commission refunded
affiliate.appliedAn affiliate has applied to join a campaign
affiliate.approvedAn affiliate has been approved for a campaign
payout.completedAn affiliate payout has been successfully disbursed

Webhook Payload Format

{
  "event": "conversion.created",
  "timestamp": "2026-04-25T10:30:00.000Z",
  "data": {
    "conversionId":    "conv_Kd8Xp2m",
    "campaignId":      "camp_abc123",
    "affiliateId":     "aff_xyz789",
    "affiliateName":   "Amina Hassan",
    "conversionType":  "sale",
    "saleValue":       250.00,
    "currency":        "USD",
    "commissionAmount": 25.00,
    "status":          "pending"
  }
}

Retry Logic

If your endpoint fails (non-2xx response or timeout), Eastlink retries:

  • Attempt 1: Immediate
  • Attempt 2: After 1 minute
  • Attempt 3: After 5 minutes
  • After 3 failures: Marked as failed in webhook logs

Verifying Signatures

Every webhook includes an X-Eastlink-Signature header — an HMAC-SHA256 signature of the raw request body using your webhook secret. Always verify this before processing the payload.

const crypto = require('crypto');

function verifyWebhook(req, webhookSecret) {
  const signature = req.headers['x-eastlink-signature'];
  const expected  = crypto
    .createHmac('sha256', webhookSecret)
    .update(JSON.stringify(req.body))
    .digest('hex');
  return signature === expected;
}

app.post('/webhook/eastlink', (req, res) => {
  if (!verifyWebhook(req, process.env.EASTLINK_WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }
  const { event, data } = req.body;
  if (event === 'conversion.created') {
    // Handle new conversion
    console.log('New conversion:', data.conversionId);
  }
  res.status(200).send('OK');
});
POST /v1/webhooks/test Any scope

Sends a test payload to a webhook URL. Useful for verifying connectivity before going live.

FieldTypeDescription
webhookUrlstringThe URL to send the test payload to

SDKs & Libraries

Official SDKs are in development. In the meantime, the REST API works directly with any HTTP client.

LanguageStatus
JavaScript / Node.jsComing Soon
PythonComing Soon
PHPComing Soon

Changelog

v1.0.0 — April 2026

Initial release of the Eastlink Enterprise API.

  • GET /v1/campaigns — list and filter merchant campaigns
  • GET /v1/campaigns/:id — single campaign with products
  • POST /v1/conversions — record conversions with deduplication
  • GET /v1/conversions — paginated conversion history
  • GET /v1/conversions/:id — single conversion detail
  • PUT /v1/conversions/:id/confirm — approve or reject conversions
  • GET /v1/affiliates — list approved affiliates with stats
  • GET /v1/analytics — aggregated metrics with byDay and byCountry breakdown
  • GET /v1/products — active product catalog
  • POST /v1/webhooks/test — verify webhook connectivity
  • Webhook delivery with HMAC-SHA256 signatures and 3-attempt retry
  • API key management with scopes and IP whitelisting
  • Rate limiting: 100 requests per minute per key