🔌 Developer API

Kreward External API

The Kreward API lets you embed your loyalty program into any website or backend. Available on the Growth (HK$450/month) and Enterprise plans.

Base URL https://api.kreward.net/v1
LLM-friendly plain text ← paste into ChatGPT / Claude

Overview

The Kreward API lets you embed your loyalty program into any website or backend. Available on the Growth (HK$450/month) and Enterprise plans.

What can you do?
• Enroll a customer and get an instant wallet card QR code
• Add or deduct points / stamps in real time
• Query a customer current balance
• Trigger a redemption from your backend

Quick start (3 steps)

  1. Get your API keys — Go to Dashboard → API and generate a key pair. You get a public key and a secret key.
  2. Test the connection — Call GET /v1/ping with your public key. You should get {"ok":true}.
  3. Enroll your first customer — Call POST /v1/enroll with an email. The response includes QR codes for Apple Wallet and Google Wallet.

Authentication

Include your API key in the Authorization header using the Bearer scheme on every request.

PUBLIC

Safe in frontend JavaScript. Enrollment only. Can be restricted by domain whitelist.

SECRET

Server-side only. Full access. Never expose in frontend code.

HTTP
Authorization: Bearer kw_pub_a3f...   # Public key
Authorization: Bearer kw_sk_9xB...    # Secret key (server only)

Errors

All errors return JSON with an error field and an HTTP status code.

{ "error": "customer_not_found" }
StatusMeaning
200Success
400Bad request — missing or invalid parameter
401Missing or invalid API key
403Forbidden — plan not eligible, or origin blocked
404Customer not found
409Conflict — e.g. insufficient balance
429Rate limit exceeded (100 req/min)
500Internal server error

Endpoints

GET/v1/pingPublic or SecretHealth check

Verify the API is reachable and your key is valid.

cURL
curl https://api.kreward.net/v1/ping \
  -H "Authorization: Bearer kw_pub_YOUR_KEY"
{ "ok": true, "merchant": "My Shop" }
GET/v1/meSecret onlyAccount info

Returns your merchant details, active card templates, and current plan.

cURL
curl https://api.kreward.net/v1/me \
  -H "Authorization: Bearer kw_sk_YOUR_SECRET"
{ "merchant": "My Cafe", "plan": "growth", "templates": [
    { "id": "uuid...", "name": "Stamp Card", "type": "stamps", "goal": 8 }
] }
POST/v1/enrollPublic or SecretEnroll + wallet QR

Enroll a customer. Creates account if needed. Returns QR codes for Apple Wallet and Google Wallet.

FieldTypeDescription
emailstringIf omitted, returns a QR linking to your enrollment page.
namestringCustomer display name (optional)
template_iduuidCard template (defaults to first active)
cURL
curl -X POST https://api.kreward.net/v1/enroll \
  -H "Authorization: Bearer kw_pub_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email":"[email protected]","name":"Jane"}'
JavaScript
const res = await fetch('https://api.kreward.net/v1/enroll', {
  method: 'POST',
  headers: { 'Authorization': 'Bearer kw_pub_YOUR_KEY', 'Content-Type': 'application/json' },
  body: JSON.stringify({ email: '[email protected]', name: 'Jane' }),
});
const data = await res.json();
// data.qr_ios / data.qr_android -> base64 PNG
PHP
$ch = curl_init('https://api.kreward.net/v1/enroll');
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER=>true,CURLOPT_POST=>true,
  CURLOPT_HTTPHEADER=>['Authorization: Bearer kw_sk_SECRET','Content-Type: application/json'],
  CURLOPT_POSTFIELDS=>json_encode(['email'=>'[email protected]','name'=>'Jane'])]);
$data = json_decode(curl_exec($ch),true);
{ "enrolled": true, "card_id": "uuid...", "balance": 0,
  "qr_ios": "data:image/png;base64,...",
  "qr_android": "data:image/png;base64,...",
  "wallet_url_ios": "https://...", "wallet_url_android": "https://..." }

Display qr_ios / qr_android as <img src="..."> — no file storage needed. Or redirect to wallet_url_ios / wallet_url_android for one-tap install.

GET/v1/customerSecret onlyQuery balance
ParamTypeDescription
email requiredstringCustomer email address
template_iduuidSpecific card template
cURL
curl "https://api.kreward.net/v1/[email protected]" \
  -H "Authorization: Bearer kw_sk_YOUR_SECRET"
{ "card_type": "stamps", "balance": 5, "goal": 8, "name": "Jane" }
POST/v1/transactionSecret onlyAdd / deduct
FieldTypeDescription
email requiredstringCustomer email
delta requiredintegerAmount to add (positive) or deduct (negative). E.g. +1 stamp, -50 points.
notestringOptional note (order ID, etc.)
template_iduuidTarget a specific template
cURL
curl -X POST https://api.kreward.net/v1/transaction \
  -H "Authorization: Bearer kw_sk_YOUR_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"email":"[email protected]","delta":1,"note":"Order #1234"}'
Node.js
await fetch('https://api.kreward.net/v1/transaction', {
  method: 'POST',
  headers: { 'Authorization': `Bearer ${process.env.KREWARD_SECRET_KEY}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({ email: order.email, delta: 1, note: order.id }),
});
PHP
wp_remote_post('https://api.kreward.net/v1/transaction', [
  'headers' => ['Authorization'=>'Bearer '.$_ENV['KREWARD_SECRET'],'Content-Type'=>'application/json'],
  'body' => json_encode(['email'=>$email,'delta'=>1,'note'=>'Order #'.$order_id]),
]);
{ "ok": true, "new_balance": 6, "card_type": "stamps", "goal": 8 }
POST/v1/redeemSecret onlyClaim a reward tier

Tiers are milestones identified by their at threshold (see GET /v1/customer). Claiming a tier marks it redeemed — it does not spend balance, except redeeming the final stamp milestone (at == stamps_total) on a stamps card, which loops the card (balance becomes the held overflow, milestones re-arm).

FieldTypeDescription
email requiredstringCustomer email
at requiredintegerThe tier threshold to claim (positive integer)
cURL
curl -X POST https://api.kreward.net/v1/redeem \
  -H "Authorization: Bearer kw_sk_YOUR_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"email":"[email protected]","at":8}'
{ "ok": true, "redeemed_at": 8, "looped": true, "redeemed_tiers": [],
  "balance_before": 8, "balance_after": 0, "card_type": "stamps" }

Plain HTML / JavaScript

Add an enrollment form to any static website in under 10 minutes using only the public key.

HTML
<form id="loyalty-form">
  <input type="email" id="lf-email" placeholder="Your email" required>
  <button type="submit">Get my loyalty card</button>
</form>
<div id="loyalty-result" style="display:none"></div>
<script>
document.getElementById('loyalty-form').addEventListener('submit', async e => {
  e.preventDefault();
  const res = await fetch('https://api.kreward.net/v1/enroll', {
    method:'POST',
    headers:{'Authorization':'Bearer kw_pub_YOUR_KEY','Content-Type':'application/json'},
    body: JSON.stringify({ email: document.getElementById('lf-email').value }),
  });
  const d = await res.json();
  if (d.qr_ios) {
    document.getElementById('loyalty-result').innerHTML =
      '<a href="'+d.wallet_url_ios+'"><img src="'+d.qr_ios+'" width="160"></a> '+
      '<a href="'+d.wallet_url_android+'"><img src="'+d.qr_android+'" width="160"></a>';
    document.getElementById('loyalty-result').style.display='block';
  }
});
</script>
Tip: Set allowed origins in the API dashboard so your public key only works from your domain.

WordPress / WooCommerce

Step 1 — Store your secret key in wp-config.php (never hardcode it in plugin files):

wp-config.php
define('KREWARD_SECRET_KEY', 'kw_sk_YOUR_SECRET');

Step 2 — Add to functions.php or a custom plugin:

PHP
add_action('woocommerce_order_status_completed', function($order_id) {
  $order = wc_get_order($order_id);
  if (!$order->get_billing_email()) return;
  wp_remote_post('https://api.kreward.net/v1/transaction', [
    'headers' => ['Authorization'=>'Bearer '.KREWARD_SECRET_KEY,'Content-Type'=>'application/json'],
    'body' => json_encode(['email'=>$order->get_billing_email(),'delta'=>1,'note'=>'Order #'.$order_id]),
  ]);
});

add_action('woocommerce_created_customer', function($customer_id) {
  $user = get_user_by('id', $customer_id);
  wp_remote_post('https://api.kreward.net/v1/enroll', [
    'headers' => ['Authorization'=>'Bearer '.KREWARD_SECRET_KEY,'Content-Type'=>'application/json'],
    'body' => json_encode(['email'=>$user->user_email,'name'=>$user->display_name]),
  ]);
});

Shopify Integration

Option A — Shopify Flow (no code)

  1. Install Shopify Flow from the App Store (free).
  2. Create a workflow triggered by "Order paid".
  3. Add a "Send HTTP request" action to POST /v1/transaction.
  4. Set the Authorization header and body with email from order.email and delta: 1.

Option B — Custom webhook (Node.js)

Node.js
app.post('/webhooks/shopify/order-paid', async (req, res) => {
  const order = req.body;
  res.sendStatus(200);
  if (!order.email) return;
  await fetch('https://api.kreward.net/v1/transaction', {
    method:'POST',
    headers:{'Authorization':`Bearer ${process.env.KREWARD_SECRET_KEY}`,'Content-Type':'application/json'},
    body:JSON.stringify({ email:order.email, delta:1, note:`Shopify ${order.name}` }),
  });
});

Security best practices

  • Never expose your secret key in frontend code or public repositories. Use environment variables.
  • Restrict allowed origins for your public key so it only works from your own domains.
  • Rotate keys if you suspect a compromise — revoke and generate a new pair instantly.
  • Use HTTPS only — the API enforces TLS.
  • Store the secret key once — shown only at creation, never recoverable.
  • Rate limit: 100 requests per minute per key.
⚠️ Your secret key gives full access to your loyalty program — anyone with it can add or remove points for any customer. Treat it like a database password.

Ready to start?