Introduction
Welcome to the Merit API! You can use our API to access Merit Giftcard platform.
This API has been created for partners to connect to the Gift Card Platform to create gift cards and send it to customers
- Current version of the API is V3 and the endpoints will be prefixed by v3/.
Authentication
Merit uses token based authentication. API keys to allow access to the API.
The client needs to send HTTP requests with the Authorization header that contains the word ‘Bearer’ followed by a space and the Key Secret.
Merit expects for the API key to be included in all API requests to the server in a header that looks like the following:
Authorization: Bearer secret_token
To authorize, use this code:
# With shell, you can just pass the correct header with each request
curl "api_endpoint_here" \
-H "Authorization: Bearer secret_key"
Make sure to replace
secret_keywith your API key.
Base URL
Base URL for Merit API endpoints
| Description | URL |
|---|---|
| Staging | https://api.sandbox.meritincentives.com |
| Host | https://api.meritincentives.com |
| Content-Type | application/json |
| Authorization | Bearer secret_token |
Giftcard Fulfillment
Single Order Async
curl --location --request POST 'https://api.sandbox.meritincentives.com/gift-cards/v3/orders/async' \
--header 'Authorization: Bearer secret_key' \
--header 'Content-Type: application/json' \
--data-raw '{
"quantity": 1,
"denomination": 10,
"product_id": "product_c92jlkj234h4b3kb8c3d",
"reference_id": "referenceId123",
"recipient": {
"first_name": "A",
"last_name": "B",
"email": "example@example.com"
},
"send_email": false
}'
The above command returns JSON structured like this:
{
"id": "f6ecc851-3aef-4a74-b03a-83fd6e22c8bc",
"status": "PROCESSING"
}
This request is for creating gift cards for a particular brand. The corresponding product_id for the brand needs to be known. This will be provided by Merit.
HTTP request
POST https://api.sandbox.meritincentives.com/gift-cards/v3/orders/async
Query Parameters
| Parameter | Required | Description |
|---|---|---|
| quantity | Yes | Integer (max of 5 quantity is allowed and min of 1) |
| denomination | Yes | Integer |
| product_id | Yes | String |
| reference_id | Yes | String (Must be case sensitive, Maximum length of 128, Allowed characters are A-Z, a-z, 0-9, :, -, @) |
| recipient | No | Json Object (Recipient) |
| send_email | No | Boolean , default : false (if send email is true, recipient.email is required and an email will be sent to the recipient) |
Single Order Async Response
| Parameter | Type | Description |
|---|---|---|
| id | UUID | Unique order id |
| status | String | Order status |
Get Order Details
This request is for getting order status and gift card url. To request this endpoint you will need to provide an order_id parameter which you can obtain in the response to the Single Order Async API .
We recommend using Webhooks to learn when an order’s status changes instead of polling this endpoint on a fixed interval. To register or update your webhook URL, contact the Merit technical team.
When you call Get Order Details whether to reconcile after a webhook, recover from a missed delivery, or retrieve full gift card payload use an exponential backoff strategy if you need to poll. Typically, an order completes within 2 minutes. In rare occurrences, if an order remains in processing status after 30 minutes, please contact our support team for assistance.
Note: Date in YYYY-MM-DD format if an expiry date is applicable; otherwise, the expiry date will be "Unlimited"
HTTP request
GET https://api.sandbox.meritincentives.com/gift-cards/v3/orders/{id}
curl --location --request GET 'https://api.sandbox.meritincentives.com/gift-cards/v3/orders/f6ecc851-3aef-4a74-b03a-83fd6e22c8bc' \
--header 'Authorization: Bearer secret_key'
The above command returns JSON structured like this:
{
"status": "COMPLETED",
"total_count": 1,
"success_count": 1,
"failed_count": 0,
"id": "f6ecc851-3aef-4a74-b03a-83fd6e22c8bc",
"reference_id": "referenceId123",
"items": [
{
"status": "COMPLETED",
"product_id": "product_c92jlkj234h4b3kb8c3d",
"currency_code": "AED",
"denomination": 10,
"giftcard": {
"card_id": "20230208-12345678",
"original_value": "10.0",
"remaining_value": "10.0",
"expiration_date": "2024-02-08",
"url": "https://giftcardpreviewlink"
},
"recipient": {
"email": "example@example.com",
"last_name": "B",
"first_name": "A"
},
"send_email": false,
"created_at": "2023-02-08T10:14:42.000Z"
}
],
"created_at": "2023-02-08T10:14:42.000Z",
"total_pages": 1,
"current_page": 1
}
Get Order Response
| Parameter | Type | Description |
|---|---|---|
| status | String | Order status |
| total_count | Integer | Total quantity of the Order |
| success_count | Integer | Total quantity of Successful orders items |
| failed_count | Integer | Total quantity of Failed orders items |
| id | UUID | Unique order id |
| reference_id | String | The reference_id sent by the client while placing the order |
| items | Array of (Order Item) | Order items status and Gift Card details |
| created_at | String | Timestamp Format ISO_8601 example “2022-10-19T14:21:00.000Z” |
| total_pages | Integer | The total number of pages that are available for the given set of data. Note: If an order has less than 100 items, the total_pages, current_page fields can be ignored as the API response will return all items. |
| current_page | Integer | Field represents the page number of the current set of data that is being returned |
Order Item
| Parameter | Type | Description |
|---|---|---|
| status | String | Order Item status |
| product_id | String | |
| currency_code | String | ISO 4217 Currency Codes |
| denomination | Integer | |
| giftcard | Giftcard | Gift card details |
| recipient | Recipient | Optional recipient for this line item (first_name, last_name, email, optional lang). See the Recipient subsection under Types for required fields and defaults |
| send_email | Bool | |
| created_at | String | Timestamp Format ISO_8601 example “2022-10-19T14:21:00.000Z” |
Giftcard
| Parameter | Type | Description |
|---|---|---|
| card_id | String | Internal Gift card id |
| original_value | String | |
| remaining_value | String | |
| expiration_date | String | Date in YYYY-MM-DD format if an expiry date is applicable; otherwise, the expiry date will be "Unlimited" |
| url | String | Redemption: Use this URL for customer redemption and for any preview or landing experience. This is the field integrations should rely on. |
Order Reprocess
curl --location --request POST ' https://api.sandbox.meritincentives.com/gift-cards/v3/orders/6e755c0d-23d0-48a3-a047-0a754bca41b8/reprocess' \
--header 'Authorization: Bearer secret_key' \
--header 'idempotency-key: b8e0183f-51a8-49cc-96be-189fc9a4a4ee' \
The above command returns JSON structured like this:
{
"id": "6e755c0d-23d0-48a3-a047-0a754bca41b8",
"status": "PROCESSING"
}
This request is for reprocessing the order that was FAILED or PARTIALLY_COMPLETED. The corresponding id from the create giftcard response needs to be provided.
HTTP request
POST https://api.sandbox.meritincentives.com/gift-cards/v3/orders/:id/reprocess
Query Parameters
| Parameter | Required | Description |
|---|---|---|
| id | Yes | Unique order id that was provided in the response of create API |
Reprocess Response
| Parameter | Type | Description |
|---|---|---|
| id | UUID | Unique order id |
| status | String | Order status |
Vendor Account
Get Account Balance
This Api returns the account balance.
HTTP request
GET https://api.sandbox.meritincentives.com/account/v3/balances
curl --location --request GET 'https://api.sandbox.meritincentives.com/account/v3/balances' \
--header 'Authorization: Bearer key'
The above command returns JSON structured like this:
{
"availableFunds": {
"amount": 47,
"currencyCode": "AED"
}
}
Get Account Balance Response
| Parameter | Type |
|---|---|
| availableFunds | Available Funds |
Types
Available Funds
| Parameter | Type |
|---|---|
| amount | Float |
| currencyCode | String ISO_4217 |
Recipient
| Parameter | Required | Type |
|---|---|---|
| first_name | No | String |
| last_name | No | String |
| Yes | String | |
| lang | No (Default en - english) | String ISO 639-1 |
Note: Language codes supported by the product will be shared by the Merit team
Order Status
| Value | Description |
|---|---|
| ACCEPTED | The order is accepted by Merit System. |
| PROCESSING | The order is currently being processed. |
| COMPLETED | The order has been fulfilled. (All requested gift cards have been placed.) |
| FAILED | The creation of all gift cards requested in an order has failed. |
| PARTIALLY_COMPLETED | A portion of the gift cards requested in the order were successfully created, while others failed. |
Order Item Status
| Value | Description |
|---|---|
| ACCEPTED | The order item is accepted by Merit System |
| PROCESSING | The order item is currently being processed. |
| COMPLETED | The order item has been fulfilled. |
| FAILED | The order item failed. |
Errors
Merit uses conventional HTTP response codes to indicate the success or failure of an API request. In general: Codes in the 2xx range indicate success. Codes in the 4xx range indicate an error that failed given the information provided (e.g., a required parameter was omitted). Codes in the 5xx range indicate an error with Merit's servers (these are rare).
Error Attributes
| Parameter | Required | Type |
|---|---|---|
| errorType | Yes | String |
| errorCode | Yes | Integer |
| errorMessage | Yes | String |
Error Types
| Type | Description |
|---|---|
| VALIDATION_ERROR | there was an issue with the data that was sent to an API |
| INVALID_REQUEST_ERROR | one or more field is missing from the request |
| FUND_ERROR | your account doesn't have enough credit to perform the action |
| ACCESS_DENIED_ERROR | don't have access to perform the action |
| SERVER_ERROR | something unexpected happened on server while processing the request. |
HTTP Status Codes
| Code | Description |
|---|---|
| 200 - OK | Everything worked as expected. |
| 400 - Bad Request | The request was unacceptable, often due to missing a required parameter. |
| 401 - Unauthorized | Invalid Security Credentials Or IP not whitelisted. |
| 404 - Not Found | The requested resource doesn't exist. |
| 409 - Conflict | The requested resource already exist. |
| 429 - Too Many Requests | Too many requests hit the API too quickly. We recommend an exponential backoff of your requests. |
| 500, 502, 503, 504 - Server Errors | Something went wrong on Merit's end. (These are rare.) |
Error codes
| Code | Description |
|---|---|
| 2001 | insufficient fund. |
| 2002 | unauthorized |
| 2003 | forbidden |
| 2004 | some required field is missing from the request |
| 2005 | invalid denomination |
| 2006 | invalid product |
| 2007 | invalid email |
| 2008 | invalid quantity |
| 2009 | invalid page number |
| 2010 | order not found |
| 2011 | invalid language |
| 2012 | idempotency-key should be in 20 - 64 characters |
| 2013 | request with idempotency-key is in-progress. Please wait! |
| 2050 | something unexpected happened on server while processing the request. |
Example: Unauthorized Response - HTTP Status Code 401
{
"errorType": "ACCESS_DENIED_ERROR",
"errorCode": 2002,
"errorMessage": "unauthorized"
}
Idempotency
Merit support idempotency to provides protection against accidental duplicate calls causing unintended consequences.
The client needs to send HTTP requests with the idempotency-key header that contains unique identifier string with a maximum of 20 - 64 characters.
If the idempotency-key is not provided, the request will be processed without considering idempotency, potentially leading to duplicate request processing.
Idempotency is applicable only to POST and DELETE calls; idempotency keys sent in GET calls will be ignored.
idempotency key header that looks like the following:
idempotency-key: XXXX-XXXXX-XXXXXX-XXXX
curl "api_endpoint_here" \
-H "idempotency-key: XXXX-XXXXX-XXXXXX-XXXX"
Throttle rate
Merit API will throttle/decline incoming requests to prevent misuse of the system. The request rate cannot exceed more than specified below.
| API | Throttle rate (# of requests) |
|---|---|
| Single Order Async | 10 per 10 seconds |
| Get Order | 60 per 10 seconds |
| Reprocess Order | 10 per 10 seconds |
When requests from your code exceed a throttle rate, your request fails and a ThrottlingException is returned with a HTTP status code 429 (Too Many Request)
Response will contain following headers.
- RateLimit-Limit: The maximum number of requests you're permitted to make per hour.
- RateLimit-Reset: the time at which the current rate limit window resets in UTC epoch seconds
Webhooks
Integration Guide
Webhooks provide a powerful mechanism to receive real-time notifications about events occurring within your Merit account. By registering a webhook URL, Merit can directly push event data to your application, enabling immediate and automated responses.
Registering a Webhook URL
To begin receiving webhook notifications, provide your webhook URL to the Merit team. Merit will register this URL and subscribe it to relevant events based on your application needs. For instance, accounts using Merit's Giftcard orders APIs will have their webhooks subscribed to related transaction events.
Upon registration, a secret key will be shared with you, essential for the secure verification of incoming notifications.
Webhook Endpoint Requirements
Your endpoint must be a HTTPS POST endpoint listening on port 443.
| Payload | Description |
|---|---|
| Body | Each webhook notification contains an Event Object in JSON format. |
| Headers | Critical headers include X-Merit-Signature, which is used for message verification. |
Handling Webhook requests
Receiving and processing webhook notifications consists of two primary steps:
- Receipt of Message:
- Your endpoint should acknowledge successful reception by returning an HTTP 2xx status code. Failure to do so prompts
Meritto retry according to its retry policy.
- Verification of Message:
- Verify the X-Merit-Signature header to ensure the authenticity of the received event. A typical signature header is as follows:
The signature contains a timestamp (t) and several signature hashes (e.g., v0, v1). To confirm the legitimacy of an event, your server must validate that at least one of these hashes matches the locally computed version.
During key rotations, it's common to receive multiple hashes under the same version. Example: "X-Merit-Signature": "t=1492774577,v0=ansdoj213e9,v0=6ffbb59b". Even in this case, your sever should make sure that at least one hash matches the locally computed version.
However, note that in normal operations, you will typically encounter only one signature hash (initially, v0) and only one hash per version.
- Verification Process:
- Concatenate the timestamp and payload in the format {timestamp},{payload}.
- Using a HMAC library, compute your signature using the secret key, the concatenated message in step 1 and encode the result in base64.
- (Optional): Verify the timestamp to ensure it's within an acceptable range (e.g., ±10 minutes) to prevent replay attacks.
- Perform a constant time comparison between the computed signature and the received signatures to safeguard against timing attacks.
Use this streamlined approach to integrate webhooks efficiently into your application, ensuring real-time responsiveness and enhanced security.
Retry Policy
Merit attempts to deliver a given event to your webhook endpoint for up to 2 days with an exponential back-off. A max of 15 requests will be attempted.
Event
Event object
| name | description |
|---|---|
| id | Unique identifier of the event |
| created_at | Unix epoch of the time at which this event is generated |
| event_type | The type of the event. The entire list of event types can be found here EventTypes |
| version | The version of the resource object which is available in the data field. This will be of no significance unless there is a version change which impacts the data structure. |
| data | Object containing the data associated with the event. The structure of the object depends on the event_type. The details of the structure can be found in |
Data Object
You will receive the orderId and order status in the webhook data. Upon receiving the webhook call, the client must make an API call to the Get Order Details API to retrieve the updated order details which include the giftcard information. The giftcard information will not be sent as part of the webhook event.
| Parameter | Type | Description |
|---|---|---|
| id | UUID | Unique order id |
| status | String | Order status |
Event Types
This is a list of all the types of events we currently send. We may add more at any time, so in developing and maintaining your code, you should not assume that only these types exist.
| Event Name | Description |
|---|---|
| giftcards.order.completed | Triggered when all items in an order are successfully completed. |
| giftcards.order.failed | Triggered when all items in an order fail. This order can be reprocessed using the Reprocess API. |
| giftcards.order.partially_completed | This is triggered when all order items reach a terminal state, either FAILED or COMPLETED, and at least one item in the order fails. The order can be reprocessed, but only the failed items will be retriedThis is triggered when all order items reach a terminal state (FAILED or COMPLETED) with at least one FAILED item. On partial completions, the typical behavior is that the client uses the reprocess API to fulfill the FAILED items. This event informs clients to facilitate reprocessing and allows them to access COMPLETED items without waiting for all items to be COMPLETED. |
Go-Live Process
To successfully transition from the test environment to production, the following steps must be completed.
- Integration Completion Confirmation - The client confirms that the API integration is successfully completed and tested in the Test Environment.
- Email Template Submission - The client shares a sample email template containing the Merit Gift Card URL, embedded as per the required format.
- Email Template Validation & Approval - The Merit Team reviews, validates, and approves the email template.
- Production Setup Requirements - The client provides their
- Production IP address
- Client shares the details of the products that need to be configured in the production environment and Merit Operations team allocates these selected products to the client catalog.
- Forecast of volumes for the selected products
- Low float balance alerts and email IDs for receiving low balance alerts emails.
- Float Amount Deposit - The client deposits the agreed float amount to the Merit account to facilitate transactions.
- Float Amount Confirmation- The Merit Finance Team confirms receipt of the float amount and updates the balance in the Merit System and set-up the low float balance thresholds.
- Production Credentials Issuance- The Merit Team configures the agreed products for the client and provides Production Vendor ID & Secret Key.
- Go-Live & Order Placement- The client integrates the production credentials, completes the final setup, and successfully places test/live orders to officially go live.