Get started
Report signups from your server
One API call after signup ties the new user to the affiliate who sent them. Ad blockers and browser privacy settings can't interfere with it, and every later Stripe payment from that user is credited automatically. It is available on every plan, including Free.
Get your server key#
Find it in Settings → Server API key. It starts with sk_kr_ and is shown in full only when you create or roll it; after that the dashboard shows just the last four characters. Keep it in an environment variable on your server.
Each program has one server key, shared by your team. Rolling it in Settings stops the old key immediately, so deploy the new one first.
Make the call#
Right after you create a user, send POST /v1/referrals with whatever you know about them and the referral from the cookie or form field.
curl
curl https://kickrail.com/api/v1/referrals \
-H "Authorization: Bearer $KICKRAIL_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{"referral":"kr_7Hq2...","email":"[email protected]","user_id":"u_1842"}'Node (Express)
app.post("/signup", async (req, res) => {
const user = await createUser(req.body);
// Report it. Don't let a Kickrail hiccup break signup.
fetch("https://kickrail.com/api/v1/referrals", {
method: "POST",
headers: {
Authorization: "Bearer " + process.env.KICKRAIL_SECRET_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
referral: req.cookies.kr_ref ?? req.body.kickrail_referral,
email: user.email,
user_id: user.id,
stripe_customer_id: user.stripeCustomerId, // if you have one already
ip: req.ip, // for self-referral checks
}),
}).catch((err) => console.warn("kickrail", err));
res.redirect("/welcome");
});Python
import os, requests
requests.post(
"https://kickrail.com/api/v1/referrals",
headers={"Authorization": f"Bearer {os.environ['KICKRAIL_SECRET_KEY']}"},
json={
"referral": request.cookies.get("kr_ref"),
"email": user.email,
"user_id": str(user.id),
"ip": request.remote_addr,
},
timeout=5,
)Body#
Send at least one of email, user_id or stripe_customer_id (otherwise 422), and at least one way to find the affiliate: referral, via or code.
| Field | Type | Description |
|---|---|---|
| referral | string | The kr_ref cookie or the kickrail_referral form field. The strongest signal: it points at an actual recorded click. |
| via | string | The affiliate token, if you only have that (for example the kr_via cookie, or a token you stored yourself). |
| code | string | A creator code the user typed into your signup form, like JANE20. |
| string | The user's email. Also used to match Stripe customers and for the self-referral check. | |
| user_id | string | Your own id for the user. Lets you look the referral up later with user_id. |
| stripe_customer_id | string | The Stripe customer (cus_...), if it exists yet. If not, Kickrail matches the customer by email when the first invoice arrives. |
| ip | string | The user's IP address. Stored only as a hash, and compared with the IPs the affiliate signs in from. |
Response#
200
{
"referred": true,
"created": true,
"referral": {
"id": "ref_9xT...",
"object": "referral",
"affiliate_id": "aff_2Lp...",
"campaign_id": "cmp_...",
"source": "link",
"status": "lead",
"email": "[email protected]",
"user_id": "u_1842",
"stripe_customer_id": null,
"flagged": false,
"rejected": false,
"first_paid_at": null,
"created_at": "2026-10-17T15:04:05Z"
}
}{"referred": false}means nothing pointed at an approved affiliate. That is the normal answer for an organic signup; you can send every signup and let Kickrail decide.created: falsemeans the person was already attributed. The first affiliate keeps them (or, with last-touch attribution, a newer link or code moves them until their first payment), and the call is safe to repeat.flagged: truemeans a self-referral check matched. Commissions for this referral wait for your review.
Look up a user later#
To show "referred by Jane" in your admin, or to decide whether to apply a referral discount:
curl
curl "https://kickrail.com/api/v1/referrals/lookup?user_id=u_1842" \
-H "Authorization: Bearer $KICKRAIL_SECRET_KEY"
# {"referred": true, "referral": { ... }}Pass one of email, user_id or stripe_customer_id. Lookup works on every plan.
After signup#
You don't report payments. Kickrail receives your Stripe webhooks and matches each invoice.paid and paid checkout.session.completed to the referral by Stripe customer, then by email. Refunds and disputes are handled the same way. See Campaigns and commissions.
Order of signals