Freebee Ads docs

Engineering docs

Merchant API — check and redeem Freebee coupons from your own system

Last updated Nov 4, 2026 · 6 sections

For merchants whose offers use codes Freebee generates. Your billing or POS system checks a code the shopper shows, redeems it once, and gets the same answer back on a retry. For offers that run on your own codes (a code pool or one shared code), you validate in your own system and send the redemptions back (the third call below).

Base URL: https://api.freebeeads.com (local: http://localhost:8001). Every call is POST with a JSON body and the header X-Api-Key: fmk_…. Times are UTC in ISO 8601 with a Z.

Keys

The owner of your Freebee account creates keys on Settings → API keys (/settings/api):

  • a key belongs to one brand and validates only that brand's coupons — another merchant's code answers not_valid_at_this_merchant;
  • optionally it is limited to some of your outlets: a redeem for another outlet answers not_valid_at_this_outlet;
  • sandbox keys answer only for the sample offer below and never touch a real coupon;
  • a revoked key is refused (401) from its very next request;
  • after 10 checks answering not_valid_at_this_merchant within 15 minutes the key is locked for 15 minutes (429 with Retry-After) and Freebee Sales are alerted. The numbers are the platform setting coupons.validation_lockout;
  • at most 60 requests a minute per key (429 with Retry-After).

The key is shown once at creation. Freebee keeps only a fingerprint of it.

1 · Check — POST /v1/merchant/coupons/check

Reads only. Checking a code a thousand times changes nothing.

curl -s https://api.freebeeads.com/v1/merchant/coupons/check \
  -H 'X-Api-Key: fmk_your_key' -H 'Content-Type: application/json' \
  -d '{"code": "FIZZ-7K3M-9PQA", "outlet_id": "optional-outlet-id"}'
{
  "valid": true,
  "status": "valid",
  "message": "The code is valid and has not been used.",
  "offer": {"campaign": "Fizz Spin", "brand": "Fizz Cola", "title": "₹100 off popcorn", "tier": "mid",
            "issued_at": "2026-11-04T10:12:00Z", "expires_at": "2026-12-04T10:12:00Z"},
  "conditions": {"terms": "Show at counter", "valid_until": "2026-12-04T10:12:00Z", "one_use": true,
                 "outlets": [{"id": "…", "name": "Inorbit kiosk"}]}
}

status is one of:

statusvalidmeaning
validtrueunused and in date
already_redeemedfalseused before (at a counter, by this API, or reported by the merchant)
expiredfalsepast the coupon's expiry
voidedfalsecancelled by Freebee Sales
not_valid_at_this_merchantfalseunknown code, or another merchant's coupon (offer is null; counts toward the lockout)
not_valid_at_this_outletfalsethe key is limited to other outlets
merchant_codes_offerfalsethe offer runs on your own codes; validate it in your system

2 · Redeem — POST /v1/merchant/coupons/redeem

Marks the code used. Send a unique X-Request-Id (up to 80 characters) with every redeem. If your call times out, retry with the same id: you get the same answer, and the code is never redeemed twice. A second redeem of the same code under a new id answers 409 already_redeemed.

curl -s https://api.freebeeads.com/v1/merchant/coupons/redeem \
  -H 'X-Api-Key: fmk_your_key' -H 'X-Request-Id: bill-20261104-000123' \
  -H 'Content-Type: application/json' \
  -d '{"code": "FIZZ-7K3M-9PQA", "outlet_id": "optional-outlet-id"}'
HTTPbody
200{"redeemed": true, "status": "redeemed", "redeemed_at": "…", "offer": {…}, "conditions": {…}}
409{"redeemed": false, "status": "already_redeemed" / "expired" / "voided" / "not_valid_at_this_outlet" / "merchant_codes_offer", …}
404{"redeemed": false, "status": "not_valid_at_this_merchant", …}
422the X-Request-Id header is missing

A replayed answer carries the header Idempotent-Replay: true.

There is no reverse action on this API. To undo a redemption, ask Freebee Sales (they reverse it on the dashboard and it is audited).

3 · Redemption data back — POST /v1/merchant/redemptions

For offers on your own codes. Send the codes you redeemed; Freebee matches each to the coupon it was issued with and marks it redeemed, labelled merchant-reported in every report and invoice. Up to 5,000 rows per call. Only code, redeemed_at and outlet are read; anything else in a row is ignored and never stored.

curl -s https://api.freebeeads.com/v1/merchant/redemptions \
  -H 'X-Api-Key: fmk_your_key' -H 'Content-Type: application/json' \
  -d '{"rows": [
        {"code": "FZ-00017", "redeemed_at": "2026-11-04", "outlet": "Inorbit kiosk"},
        {"code": "FZ-00042", "redeemed_at": "2026-11-04 18:30", "outlet": "Online"}
      ]}'
{"total": 2, "matched": 1,
 "unmatched": [{"row": 2, "code": "FZ-00042", "reason": "This code was never issued to a player."}]}

redeemed_at accepts YYYY-MM-DD, YYYY-MM-DD HH:MM, DD/MM/YYYY and DD-MM-YYYY; blank means now. Reasons for an unmatched row: no such code in your offers · never issued to a player · already reported earlier · already redeemed at the counter · the date could not be read · a shared-code offer (one code for every winner cannot be matched to one coupon).

The same file can be uploaded on the campaign page (Coupon codes → Merchant redemption data) as .csv or .xlsx with the columns code, redeemed_at (or date) and outlet (or channel).

Sandbox

Create a key with Sandbox ticked. It answers only for the sample offer Sandbox Café — One free filter coffee and keeps its own redeem state, so you can rehearse the whole flow:

codeanswer
SBOX-OK01-TEST, SBOX-OK02-TEST, SBOX-OK03-TESTvalid until you redeem it with this key, then already_redeemed
SBOX-USED-TESTalready_redeemed
SBOX-EXPD-TESTexpired
anything elsenot_valid_at_this_merchant (and counts toward the lockout, like live keys)

Sandbox answers carry "sandbox": true. POST /v1/merchant/redemptions with a sandbox key records nothing and lists every row back as unmatched.

Errors

HTTPwhen
401missing, unknown or revoked key
422the body is not valid JSON of the right shape, or X-Request-Id is missing on redeem
429the key is locked after failed checks, or over 60 requests a minute (Retry-After seconds)

Every answer is JSON; errors carry {"detail": "…"} in plain words.

Merchant API · Docs