API untuk mitra yang membangun aplikasi cashback sendiri di atas LinkCash.id. Dipanggil dari server mitra (bukan dari aplikasi/peramban pengguna), berformat JSON lewat HTTPS.
GET /ping.Base URL:
https://api.linkcash.id/v1
curl https://api.linkcash.id/v1/ping -H "Authorization: Bearer $LINKCASH_API_KEY"
Postman: Import → pilih berkas openapi.yaml → di tab Authorization koleksinya pilih Bearer Token dan isi API key. Ingat: permintaan hanya diterima dari IP terdaftar, jadi daftarkan juga IP tempat kamu menjalankan Postman.
GET /merchants) dan/atau produk (GET /products) di aplikasimu.POST /links dengan user_id milikmu → dapat link https://linkcash.id/go/….pending → kamu menerima callback, atau menariknya lewat GET /conversions.approved, lalu paid setelah dibayarkan ke mitra. Pesanan batal/retur menjadi rejected.Satu tingkat. Pendapatan dihitung per transaksi untuk akun mitra (earning). Pembagian ke user — termasuk skema referral/berjenjang apa pun — sepenuhnya diatur di sistemmu sendiri.
Authorization: Bearer lc_live_xxxxxxxxxxxxxxxxxxxxxxxx
403 ip_not_allowed; pesannya memuat IP yang terlihat oleh server kami supaya mudah dilaporkan.429 rate_limited + header Retry-After (detik). Percobaan berulang dengan key salah dari satu IP diblokir sementara.{ "error": { "code": "unsupported_url", "message": "Link ini bukan dari toko yang didukung. Lihat GET /merchants." } }
Andalkan code di programmu; message bisa berubah.
| HTTP | code | Arti |
|---|---|---|
| 400 | invalid_request | Parameter/body salah atau kurang. |
| 401 | unauthorized | Header Authorization tidak ada, atau key tidak dikenali. |
| 403 | client_disabled · ip_not_allowed | Akun dinonaktifkan · IP belum didaftarkan. |
| 404 | not_found · merchant_not_found · product_not_found | Alamat/transaksi, toko, atau produk tidak ada. |
| 422 | unsupported_url | Link bukan dari toko yang didukung. |
| 422 | product_not_eligible | Produk itu tidak ikut program komisi tokonya — minta user memilih produk lain. |
| 422 | url_required | Toko ini hanya mendukung link per produk; kirim url. |
| 422 | callback_not_set | URL callback belum didaftarkan. |
| 429 | rate_limited · too_many_failed_attempts | Lihat header Retry-After. |
| 503 | merchant_unavailable · temporarily_unavailable · maintenance | Sementara; coba lagi nanti. |
| 500 | server_error | Kesalahan di sisi kami. |
Daftar toko yang bisa dibuatkan link.
{ "data": [ {
"slug": "traveloka", "name": "Traveloka", "category": "Travel",
"homepage": "https://www.traveloka.com", "logo": "https://…/traveloka.svg",
"rate_text": "s/d 6%", "max_rate_pct": 6,
"store_link": true, "product_link": false
} ] }
rate_text / max_rate_pct — estimasi tertinggi pendapatanmu dari nilai belanja, sudah disesuaikan dengan porsi komisi akunmu. Nilai pasti per pesanan ada di transaksi.store_link — bisa dibuatkan link ke beranda toko (kirim merchant). product_link — bisa dibuatkan link ke produk tertentu (kirim url).Katalog produk yang bisa dicari. Parameter: q (kata kunci; kosong = produk pilihan), page (1–200), limit (1–50, bawaan 20).
{ "data": [ {
"product_id": 555, "name": "Sepatu Lari", "image": "https://…jpg",
"price": 200000, "original_price": 250000, "platform": "tokopedia",
"category": "Olahraga", "shop_name": "",
"est_rate_pct": 1.5, "est_earning": 3000
} ], "page": 1, "has_more": false }
Buat link-nya dengan product_id. Katalog diperbarui tiap hari — jangan menyimpan product_id terlalu lama.
Membuat link cashback untuk satu user. Body JSON berisi user_id dan tepat satu dari:
| Field | Dipakai saat |
|---|---|
merchant | User membuka toko (slug dari GET /merchants yang store_link-nya true). |
url | User menempel link produk yang disalin dari aplikasi toko. Boleh berupa teks "Bagikan" utuh — link-nya dicari otomatis. |
product_id | User memilih produk dari GET /products. |
curl -X POST https://api.linkcash.id/v1/links \
-H "Authorization: Bearer $LINKCASH_API_KEY" -H "Content-Type: application/json" \
-d '{"user_id":"u-1001","merchant":"traveloka"}'
{ "code": "k3m9x2p7qa", "url": "https://linkcash.id/go/k3m9x2p7qa",
"merchant": "traveloka", "scope": "store", "user_id": "u-1001",
"clicks": 0, "created_at": "2026-09-20T09:00:00Z" }
user_id: ID user di sistemmu, 1–64 karakter A-Z a-z 0-9 . _ : @ -. Pakai ID internal, jangan data pribadi (email/nomor HP). Nilai inilah yang kembali di transaksi.scope: "store" berarti link menuju beranda toko. Untuk sebagian toko, link produk yang dikirim lewat url tetap menghasilkan link toko — user lalu mencari produknya di sana; transaksinya tetap tercatat.200, bukan 201) — aman diulang saat ragu permintaan sebelumnya sampai.Transaksi akunmu, terbaru lebih dulu. Filter: status, user_id, updated_since (RFC 3339), limit (1–200, bawaan 50), cursor.
{ "data": [ {
"id": "trx_1024", "user_id": "u-1001", "merchant": "Traveloka", "order_id": "ORD-778812",
"amount": 200000, "commission_pct": 50, "earning": 5000, "status": "pending",
"created_at": "2026-09-20T09:00:00Z", "updated_at": "2026-09-20T09:00:00Z"
} ], "next_cursor": "1023" }
earning = pendapatanmu (Rp). commission_pct = porsi komisi yang berlaku untuk transaksi itu; tidak berubah lagi walau porsi akunmu diubah kemudian. amount/earning bisa terkoreksi selama status masih pending.cursor=<next_cursor> sampai next_cursor bernilai null.updated_since — perubahan status ikut terbawa./conversions/{id} mengambil satu transaksi.{ "currency": "IDR", "commission_pct": 50,
"earning": { "pending": 12500, "approved": 40000, "paid": 150000, "rejected": 3000 } }
Kalau URL callback didaftarkan (wajib https://, alamat publik), kami mengirim POST JSON ke sana saat transaksimu tercatat (conversion.created) dan saat status/nilainya berubah (conversion.updated). Isi data sama persis dengan objek transaksi di atas.
POST /linkcash/callback
Content-Type: application/json
X-LinkCash-Event: conversion.updated
X-LinkCash-Timestamp: 1790000000
X-LinkCash-Signature: sha256=5f2b…
{ "event": "conversion.updated", "created_at": "2026-10-25T03:00:00Z", "data": { "id": "trx_1024", "status": "approved", … } }
Tanpa ini siapa pun yang tahu URL-mu bisa mengirim transaksi palsu. Rumusnya: HMAC-SHA256(secret, timestamp + "." + body_mentah), heksadesimal, diawali sha256=. Pakai body mentah (sebelum di-parse), bandingkan dengan fungsi aman-waktu, dan tolak kalau selisih timestamp lebih dari 5 menit.
// PHP
$body = file_get_contents('php://input');
$ts = $_SERVER['HTTP_X_LINKCASH_TIMESTAMP'] ?? '';
$sig = $_SERVER['HTTP_X_LINKCASH_SIGNATURE'] ?? '';
$mau = 'sha256=' . hash_hmac('sha256', $ts . '.' . $body, getenv('LINKCASH_CALLBACK_SECRET'));
if (!hash_equals($mau, $sig) || abs(time() - (int)$ts) > 300) { http_response_code(401); exit; }
$event = json_decode($body, true); // aman diproses
http_response_code(204);
// Node.js (Express) — pastikan body mentah tersedia: express.raw({ type: 'application/json' })
const crypto = require('crypto');
app.post('/linkcash/callback', express.raw({ type: 'application/json' }), (req, res) => {
const ts = req.get('X-LinkCash-Timestamp') || '', sig = req.get('X-LinkCash-Signature') || '';
const mau = 'sha256=' + crypto.createHmac('sha256', process.env.LINKCASH_CALLBACK_SECRET)
.update(ts + '.').update(req.body).digest('hex');
const sah = sig.length === mau.length && crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(mau));
if (!sah || Math.abs(Date.now() / 1000 - Number(ts)) > 300) return res.sendStatus(401);
const event = JSON.parse(req.body); // aman diproses
res.sendStatus(204);
});
data.id sebagai kunci dan proses secara idempoten (timpa dengan keadaan terbaru).GET /conversions?updated_since=… sebagai jaring pengaman.Mengirim event ping ke URL callback-mu saat itu juga dan melaporkan hasilnya — untuk menguji penerima dan verifikasi tanda tanganmu tanpa menunggu transaksi sungguhan.
{ "delivered": true, "url": "https://api.mitra.com/linkcash/callback", "http_status": 204 }