API reference · v1

One resource to learn: the drop.

A drop is one reward on its way. You create it, the recipient claims it, we ship it. Create, read, listen for events. That's all there is.

base · https://api.rewardics.com sandbox · api.sandbox.rewardics.com

Authentication

Send your secret key as a bearer token. A key only ever sees your own drops.

curl https://api.rewardics.com/v1/drops \
  -H "Authorization: Bearer sk_live_4Xa9…" \
  -H "Idempotency-Key: evt_88213"
sk_live_ · sk_test_

Server side only. Rotate from the dashboard, two keys can be live during a switch.

Idempotency-Key

Pass your own event ID so a retry can't send two rewards.

Claim status lifecycle

A drop only moves forward. Nothing that ends at expired gets invoiced.

created Drop exists, claim link generated, nothing sent to the recipient yet.
claim_opened Recipient opened the claim page. Handy for your reminder emails.
claimed Item picked and a checked address on file.
fulfilling We're buying the item and doing the paperwork.
shipped The courier has the parcel. Tracking sits on the drop.
delivered Signature or proof of delivery attached. Done.
expired · cancelled Nobody claimed it, or you cancelled in time. No charge.
POST

/v1/drops

Creates a drop and gives you back a claim link on your subdomain. Either the recipient picks from a catalog, or you set the item and the page only asks for an address.

ParameterTypeNotes
modestringRequired. catalog_choice or predetermined.
catalogstringCatalog ID. Required in catalog_choice mode.
itemstringSKU. Required in predetermined mode.
recipientobjectYour own reference, plus an email or phone if you want us to send the link.
claim_window_hoursintegerDefault 720. After this the drop moves to expired.
notifybooleanSet false and we just hand you the link to send yourself.
metadataobjectUp to 20 keys, sent back on every webhook for this drop.
Request · catalog_choice
{
  "mode": "catalog_choice",
  "catalog": "tier_diamond_eu",
  "recipient": {
    "reference": "player_88213",
    "email": "ivan@example.com",
    "country": "HR"
  },
  "claim_window_hours": 336,
  "metadata": { "campaign": "sept_vip" }
}
Request · predetermined
{
  "mode": "predetermined",
  "item": "sku_chrono_watch_42",
  "recipient": {
    "reference": "player_90114",
    "email": "j.kask@example.com",
    "country": "EE"
  },
  "notify": false,
  "metadata": { "trigger": "tier_up" }
}
201 Created
{
  "id": "drop_9F2K41",
  "status": "created",
  "mode": "catalog_choice",
  "claim_url": "https://acme.rewardics.com/c/9F2K41",
  "claim_expires_at": "2026-09-17T09:00:00Z",
  "metadata": { "campaign": "sept_vip" }
}
GET

/v1/drops/:id

Returns the status, the claimed item, tracking and the delivery record once it's signed.

200 OK
{
  "id": "drop_9F2K41",
  "status": "delivered",
  "claimed_item": { "sku": "sku_chrono_watch_42", "name": "Chrono watch" },
  "shipment": {
    "carrier": "DHL Express",
    "tracking": "7291043882",
    "shipped_at": "2026-09-04T11:22:00Z",
    "delivered_at": "2026-09-06T08:41:00Z",
    "signature": { "name": "I. Horvat", "proof_url": "…/pod/9F2K41.pdf" }
  }
}

List with GET /v1/drops?status=shipped&created_after=… for lists. Cursor paginated, 100 per page.

Webhook events

Signed with HMAC-SHA256 over the raw body in the Rewardics-Signature header. We retry for 24 hours. Answer 2xx within 5 seconds.

drop.claim_opened
Recipient viewed the page.
drop.claimed
Item and address captured.
drop.shipped
Carrier and tracking assigned.
drop.delivered
Signed proof of delivery attached.
drop.delivery_exception
Address or courier problem. We're on it.
drop.expired
Claim window closed unused. Not billed.
Payload · drop.delivered
{
  "event": "drop.delivered",
  "created_at": "2026-09-06T08:41:12Z",
  "data": {
    "id": "drop_9F2K41",
    "status": "delivered",
    "signature": { "name": "I. Horvat", "captured_at": "2026-09-06T08:41:00Z" },
    "metadata": { "campaign": "sept_vip" }
  }
}

Rate limits & errors

Limits
Writes100 / min
Reads600 / min
Bulk CSV rows5,000 / file

Ask us and we'll raise it. Limits report in X-RateLimit-Remaining; a 429 includes Retry-After.

Error shape
{
  "error": {
    "type": "invalid_request",
    "code": "catalog_unavailable_in_country",
    "message": "tier_diamond_eu cannot ship to BR.",
    "param": "catalog"
  }
}
Want sandbox keys today?

Sandbox drops run the whole lifecycle on a fast clock, so you can test webhooks in minutes.

Request access