> For the complete documentation index, see [llms.txt](https://help.dollarlabs.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://help.dollarlabs.io/dollarback-store-credit/earning-cashback-programs/custom-rewards-via-api.md).

# Custom rewards via API

{% embed url="<https://dollarlabs.neetorecord.com/watch/068497057337a7f7d2d1>" %}

*This article's section starts at 0:00 in the video.*

The **Custom (API)** program type lets you reward anything DollarBack can't see on its own: product reviews, UGC submissions, in-store visits, quiz completions. You define the reward in the admin; your server triggers it with one API call.

## Prerequisites

* A Merchant API key; generate one under **DollarBack admin → Merchant API** (also reachable from **Settings → Developer API**). See [Merchant API: keys & endpoints](/dollarback-store-credit/developer-tools/merchant-api-keys-and-endpoints.md).
* A server to call the endpoint from. Never call the Merchant API from storefront JavaScript; the key must stay server-side.

## Step 1: Create the custom config

1. Open **DollarBack admin → Cashback** and choose the **Custom (API)** type.
2. Set the credit amount and optional start/end dates.
3. In the **API Reward** section, optionally check **Limit how many times each customer can earn this reward** and set the frequency fields. Limits are enforced server-side on every API call.
4. Save, enable the config, and copy its **config ID**. Your server needs it.

Custom rewards are granted **only** when you call the endpoint with this config's ID. They are never triggered by Shopify webhooks or storefront actions.

## Step 2: Call the endpoint

```
POST /api/v1/merchant/custom
```

| Header              | Value                      |
| ------------------- | -------------------------- |
| `X-DollarBack-Shop` | `your-store.myshopify.com` |
| `Authorization`     | `Bearer <your API key>`    |
| `Content-Type`      | `application/json`         |

| Body field         | Type             | Required | Meaning                             |
| ------------------ | ---------------- | -------- | ----------------------------------- |
| `configId`         | string           | Yes      | The custom config's ID from Step 1  |
| `customerId`       | string or number | Yes      | The numeric Shopify customer ID     |
| `customerCurrency` | string           | Yes      | Currency to credit in, e.g. `"USD"` |

Example:

```bash
curl -X POST "https://<app host>/api/v1/merchant/custom" \
  -H "X-DollarBack-Shop: your-store.myshopify.com" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "configId": "YOUR_CONFIG_ID",
    "customerId": "7345098912345",
    "customerCurrency": "USD"
  }'
```

The exact request base URL, your key, and a copy-ready snippet are shown on the **Merchant API** page in the admin.

## Responses

| Status | Body                                                                                                    | Meaning                                                                                               |
| ------ | ------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| 200    | `{ "success": true, "requestId": "…", "message": "Custom reward is being processed" }`                  | Accepted; the credit is processed asynchronously and lands within a few seconds                       |
| 400    | `{ "error": "invalid_config", "reason": "not_found" \| "not_custom" \| "disabled" \| "not_scheduled" }` | The `configId` doesn't exist, isn't a Custom (API) config, is disabled, or is outside its date window |
| 400    | `{ "error": "missing_fields: …" }` or `{ "error": "invalid_json" }`                                     | Malformed request                                                                                     |
| 401    | `{ "error": "unauthorized" }`                                                                           | Wrong or missing API key / shop header                                                                |
| 500    | `{ "error": "internal" }`                                                                               | Retry later                                                                                           |

{% hint style="warning" %}
Passing another config type's ID returns `400 invalid_config` with reason `not_custom`; only configs created as **Custom (API)** can be dispatched through this endpoint. Per-customer frequency limits are enforced server-side, so a limited customer isn't credited again.
{% endhint %}

## Verify it works

1. Send the request for a test customer and confirm the `200` response.
2. Within a few seconds the credit appears in **DollarBack admin → Analytics → Activity**, tagged with the config name.
3. The customer sees the balance in the widget and account, and receives the credited email if enabled.

## Common issues

* `401 unauthorized`: key revoked or headers wrong; regenerate under [Merchant API: keys & endpoints](/dollarback-store-credit/developer-tools/merchant-api-keys-and-endpoints.md).
* `200` but no credit: check the config's frequency limit and the customer ID; then [A customer didn't receive cashback](/dollarback-store-credit/troubleshooting-and-faq/customer-didnt-receive-cashback.md).
* Credit in the wrong currency: `customerCurrency` controls the credited currency; send the customer's own currency.

## Related articles

* [Merchant API: keys & endpoints](/dollarback-store-credit/developer-tools/merchant-api-keys-and-endpoints.md)
* [Cashback program types at a glance](/dollarback-store-credit/earning-cashback-programs/cashback-program-types-at-a-glance.md)
* [Set up birthday rewards](/dollarback-store-credit/earning-cashback-programs/set-up-birthday-rewards.md)
* [When credit is issued](/dollarback-store-credit/earning-cashback-programs/when-credit-is-issued.md)
