RecoverKit developer docs

Connect a website, a server and past customers to this RecoverKit server. Your keys are on the Developers page of your dashboard.

1. Your connection details

Server addressRK_ENDPOINThttps://recoverkit.padiconnect.com
Public keyRK_PUBLIC_KEY. Safe in websites and appsrk_pub_YOUR_PUBLIC_KEY
Secret keyRK_SECRET_KEY. Server only, never in a website or appAsk the business owner
Add to your app's .env
RK_PUBLIC_KEY=rk_pub_YOUR_PUBLIC_KEY
RK_SECRET_KEY=rk_sec_YOUR_SECRET_KEY
RK_ENDPOINT=https://recoverkit.padiconnect.com

The business owner creates a secret key on the Developers page of their RecoverKit dashboard and sends it to you privately.

2. Your website

Before </body> on every page
<script src="https://recoverkit.padiconnect.com/sdk/recoverkit.js"></script>
<script>RecoverKit.init({ key: 'rk_pub_YOUR_PUBLIC_KEY' });</script>
JavaScript
// After sign-up or login, when you know who the user is:
RecoverKit.identify({ email: user.email, phone: user.phone });

// After logout:
RecoverKit.reset();

Works with any site: plain HTML, WordPress, Laravel Blade, React, Vue, Next.js. Emails and phone numbers are hashed in the browser. The script never reads form fields or card details, and it respects "Do Not Track". The browser can't record a sale: that comes from your server or payment gateway, below.

3. Your server: record real sales

PHPLaravel, WordPress, CodeIgniter, plain PHP
Download (or use the zip below)
mkdir -p recoverkit-php && cd recoverkit-php
curl -fsSL -O https://recoverkit.padiconnect.com/sdk/php/RecoverKit.php
PHP
<?php
require_once __DIR__ . '/recoverkit-php/RecoverKit.php';
$rk = new RecoverKit(getenv('RK_PUBLIC_KEY'), getenv('RK_SECRET_KEY'), getenv('RK_ENDPOINT'));

// After sign-up or login:
$rk->identify(['email' => $user->email, 'phone' => $user->phone, 'firstName' => $user->first_name]);

// when a payment for an order really succeeds (amount in kobo):
$rk->trackPurchase(['email' => $user->email, 'amount' => 150000, 'ref' => $order->reference]);

Laravel: put the three values in .env, read them in config/services.php, then use config(...) instead of getenv.

Node.jsExpress, NestJS, Next.js API routes
Install
npm install recoverkit
JavaScript
import { RecoverKit } from 'recoverkit';
const rk = new RecoverKit({
  publicKey: process.env.RK_PUBLIC_KEY,
  secretKey: process.env.RK_SECRET_KEY,
  endpoint: process.env.RK_ENDPOINT,
});

// After sign-up or login:
await rk.identify({ email: user.email, phone: user.phone, firstName: user.firstName });

// when a payment for an order really succeeds (amount in kobo):
await rk.trackPurchase({ email: user.email, amount: 150000, ref: order.reference });
Python, Go, Ruby, Java, C# or anything elseCall the HTTP API directly
Python example
import hashlib, os, requests

PK, SK, BASE = os.environ["RK_PUBLIC_KEY"], os.environ["RK_SECRET_KEY"], os.environ["RK_ENDPOINT"]

def rk_id(kind, value):  # kind "e" = email (trimmed, lower case), "p" = phone (digits with country code)
    return hashlib.sha256(f"rk1|{PK}|{kind}|{value}".encode()).hexdigest()

def rk_send(email, events=None, first_name=None):
    body = {"ids": [rk_id("e", email.strip().lower())], "contact": {"email": email, "firstName": first_name}}
    if events: body["events"] = events
    try:
        requests.post(f"{BASE}/v1/server/events", json=body, timeout=3,
                      headers={"Authorization": f"Bearer {SK}"})
    except requests.RequestException:
        pass  # never let RecoverKit break your checkout

rk_send(user.email, first_name=user.first_name)                      # after sign-up or login
rk_send(user.email, [{"type": "purchase", "amount": 150000, "ref": order.ref}])  # a real sale, in kobo
curl
curl -X POST https://recoverkit.padiconnect.com/v1/server/events \
  -H "Authorization: Bearer $RK_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"ids": ["<sha256 of rk1|rk_pub_YOUR_PUBLIC_KEY|e|customer@example.com>"],
       "events": [{"type": "purchase", "amount": 150000, "currency": "NGN", "ref": "ORDER-1001"}]}'

Hash each email as sha256("rk1|PUBLIC_KEY|e|" + email.trim().toLowerCase()). Phones use p and digits only with the country code (2348031234567). Full rules: API reference.

Calls time out after 3 seconds and never throw, so RecoverKit can't break a purchase. Pass your order or payment reference as ref: a sale reported twice (by your server and a gateway webhook) is counted once.

4. Payment gateway webhooks

Paystack, Flutterwave, Monnify, Stripe or any gatewayThe business owner adds the gateway in the dashboard under Payments, then pastes the webhook URL it shows into the gateway's settings. No code needed.

5. Past customers (read-only connector)

Quickest: ask the business owner for an install command (Developers page → Create install command) and run it in your app's folder. It connects, finds your database and sets everything up by itself. The steps below are the manual way.

The connector runs on your server, next to your database. It reads your tables where they are (nothing is exported), works out who signed up, bought and went quiet, and sends only hashes, dates and amounts. It looks at table and column names only, suggests a mapping, shows you a dry run, and asks before saving.

MySQL, MariaDB, PostgreSQL or SQLiteAny language or framework, on a server with PHP 7.4+ (most hosting has it)
Download, outside public_html
mkdir -p ~/recoverkit-php && cd ~/recoverkit-php
curl -fsSL -O https://recoverkit.padiconnect.com/sdk/php/RecoverKit.php -O https://recoverkit.padiconnect.com/sdk/php/recoverkit-connector.php -O https://recoverkit.padiconnect.com/sdk/php/recoverkit-detect.php
Download the zip insteadFor cPanel: upload it with File Manager and extract it in your home folder.
Set up, then send your history
export RK_PUBLIC_KEY=rk_pub_YOUR_PUBLIC_KEY
export RK_SECRET_KEY=rk_sec_YOUR_SECRET_KEY
export RK_ENDPOINT=https://recoverkit.padiconnect.com

php recoverkit-connector.php setup --app=/path/to/your/app
php recoverkit-connector.php sync
Cron: keep it up to date every 15 minutes
*/15 * * * * cd $HOME/recoverkit-php && php recoverkit-connector.php sync --app=/path/to/your/app >> sync.out 2>&1

--app lets it find your database login in your app's config: Laravel, WordPress and WooCommerce (classic and HPOS), CodeIgniter, Django, Rails, Prisma, Spring Boot, ASP.NET, or any .env with DATABASE_URL. It also reads the three RK_ values from that .env, so the cron line needs no secrets. Or set RK_DB_DSN, RK_DB_USER and RK_DB_PASS yourself: a read-only database login is best.

MongoDBNode.js apps with Mongoose, Prisma or the MongoDB driver
Run in your app folder (Node 20+)
cd /path/to/your/app
npx recoverkit-connector@1 setup --app=.
npx recoverkit-connector@1 sync --app=.
Cron
*/15 * * * * cd /path/to/your/app && npx recoverkit-connector@1 sync --app=. >> recoverkit-sync.out 2>&1

It finds your connection string in your code and .env, and checks your MongoDB login can only read. Orders stored inside customer documents are supported.

No PHP on the serverUse Docker
Docker
docker build -t recoverkit-connector https://github.com/Light8749/recoverkit.git#main:sdk/php

docker run --rm -it --network host -v /path/to/your/app:/app:ro -v recoverkit-state:/state \
  -e RK_PUBLIC_KEY -e RK_SECRET_KEY -e RK_ENDPOINT recoverkit-connector setup --app=/app --dir=/state

Your app folder is mounted read-only. Run the same command with sync from cron.

Every query the connector runs is written to recoverkit-connector.log on your server. If your tables change, it stops and asks you to run setup again. To cut it off, revoke its secret key in Settings.

6. Check it works

OverviewThe yellow warning disappears once a real sale arrives from your server or a gateway
LeadsPeople who signed up and didn't buy, or bought once and went quiet, appear here
SettingsShows each connector sync: when, how many people and records

API reference

Basics

Base URLhttps://recoverkit.padiconnect.com
FormatJSON request and response bodies
Server callsSecret key. Only from your serverAuthorization: Bearer rk_sec_…
Browser callsPublic key. Write-only, can never record a saleX-RK-Key: rk_pub_…
AmountsKobo, cents: ₦1,500 is 150000Integers in minor units
Errors400 bad input, 401 bad key, 403 origin not allowed, 429 too many requests{ "error": "message" }

Identity hashes

Formula
id = sha256_hex("rk1|" + PUBLIC_KEY + "|" + kind + "|" + value)
Email (kind e)Trim spaces and lower-case it: " Ada@Shop.NG " becomes ada@shop.ng
Phone (kind p)Digits only with the country code, no +: 0803 123 4567 becomes 2348031234567

RecoverKit never needs raw emails or phones to match people: send up to 4 hashes per person as ids. Send raw contact details in contact only if you want RecoverKit to message them; they are stored encrypted.

POST /v1/server/events secret key

Identify a person and record what they did. Send contact to let RecoverKit message them. Up to 50 events per call.

{
  "ids": ["<email hash>", "<phone hash>"],
  "contact": { "email": "ada@shop.ng", "phone": "2348031234567", "firstName": "Ada" },
  "anonId": "a_3f2c...",            // optional: the browser SDK's anonymous id
  "events": [
    { "type": "purchase", "amount": 150000, "currency": "NGN", "ref": "ORDER-1001" }
  ]
}

event types: purchase, wallet_funded, registered, checkout_started, custom
fields: type, amount (minor units; required for purchase and wallet_funded),
        currency (3 letters), ref (your order/payment reference, no spaces),
        name ([A-Za-z0-9_.:/-], up to 64), ts (milliseconds, up to 7 days old)

Response

{ "ok": true, "person": "identified", "purchases": [ ... ] }
POST /v1/server/erase secret key

Delete everything RecoverKit holds about one person (right to erasure).

{ "ids": ["<email hash>"] }

Response

{ "ok": true, "erased": true }
POST /v1/collect public key

Used by the browser and React Native SDKs. Records page views, checkout starts and other signals. It can never record a purchase. Most developers use the script instead of calling this directly.

{
  "key": "rk_pub_...",
  "anonId": "a_3f2c...",
  "ids": ["<email hash>"],          // optional, after identify
  "events": [{ "type": "page_view", "path": "/pricing" }]
}

event types: page_view, click, form_submit, checkout_started, payment_signal, registered, custom

Response

{ "ok": true, "accepted": 1 }
POST /v1/webhooks/{gatewayId} gateway signature

Where your payment gateway sends its webhooks. The URL, with its gateway id, is shown in the dashboard under Payments. Signatures are checked with the secret you saved there.

POST /v1/connector/sync secret key

Used by the read-only connectors to send history. You don't need to call it yourself.

Limits

Server calls12,000 a minute per business
Browser calls300 a minute per visitor
Events per call50