Loyalty API
qiibee Loyalty API Documentation
qiibee uses conventional HTTP response codes to indicate the success or failure of an API request.
In general, the 2xx range indicates success, the 4xx range indicates an error due to bad data or an authentication failure. And the 5xx range indicates an error with qiibee's servers (these are rare).

Base URL

The Base URL for all API requests is https://bwaapi.qiibee.com/api/admin

Authentication

All API endpoints are authenticated with the X-API-KEY header.
If you do not send the header, or the header is invalid we will return a 401 with an error message Missing x-api-key header or Invalid API Key.

Postman Collection

You can use this Postman collection to test all endpoints.
You will need to set the following environment variables:
  • qiibee_loyalty_api_base_url
  • qiibee_loyalty_api_key
  • auth_id
  • token_id
  • campaign_id
qiibee Loyalty API.postman_collection.json
16KB
Code
qiibee Loyalty API Postman Collection

Endpoints

Users

Create User

POST /users
Only the email field is mandatory.
We recommend you send a unique UUID-v4 auth_id for every new user registration so you can map each user to your internal system. If you do not send this field we will generate a UUID-v4 and return it to you.
Please save the auth_id and use it for all actions on a user's account.
eg.
1
{
2
"user": {
3
"id": "3r2esf3423r",
4
"email": "[email protected]",
5
"auth_id": "e24c962d-c81c-4a01-b0cd-57dd233553f1",
6
"first_name": "John",
7
"second_name": "Doe",
8
"language": "en",
9
"country_ISO": "usa"
10
}
11
}
Copied!

Responses

  • Created: HTTP 201 with the user object
  • Bad data: HTTP 400 with error message
    • eg. duplicate auth_id

Update User details

PUT /users/:auth_id || PATCH /users/:auth_id
You can update every field besides the auth_id
eg.
1
{
2
"user": {
3
"id": "3r2esf3423r",
4
"email": "[email protected]",
5
"first_name": "John",
6
"second_name": "Smith",
7
"language": "it",
8
"country_ISO": "usa"
9
}
10
}
Copied!

Responses

  • Update: HTTP 200 with the user object
  • Not found: HTTP 404 with error message

Get User Details

GET /users/:auth_id

Responses

  • Success: HTTP 200 with the user object:
    • 1
      {
      2
      "user": {
      3
      "id": "3r2esf3423r",
      4
      "email": "[email protected]",
      5
      "auth_id": "e24c962d-c81c-4a01-b0cd-57dd233553f1",
      6
      "first_name": "John",
      7
      "second_name": "Doe",
      8
      "language": "en",
      9
      "country_ISO": "usa"
      10
      }
      11
      }
      Copied!
  • Bad data: HTTP 404 with error message
    • eg. not found

Get User Balances

GET /users/:auth_id/balances
Will return an array of balances with the token type (erc20 or erc721).
Token types
  • erc20 is a regular token
  • erc721 is an NFT token
eg.
1
{
2
"data": [
3
{
4
"balance": 100,
5
"token": {
6
"id": "23421",
7
"address": "0x..924",
8
"name": "My Token Name",
9
"symbol": "MTN",
10
"onramp": "242",
11
"offramp": "235",
12
"estimated_member_count_lower": "1000",
13
"estimated_member_count_higher": "5000",
14
"status": [null, "pending", "approved", "rejected"],
15
"type": "erc20",
16
"metadata": { "key": "value" }
17
}
18
},
19
{
20
"status": [null, "pending", "approved", "rejected"],
21
"personalised_data": { "key": "value" },
22
"token": {
23
"id": "23421",
24
"address": "0x..924",
25
"name": "My NFT Token Name",
26
"symbol": "MTN",
27
"onramp": "242",
28
"offramp": "235",
29
"estimated_member_count_lower": "1000",
30
"estimated_member_count_higher": "5000",
31
"type": "erc721",
32
"metadata": { "key": "value" }
33
}
34
}
35
]
36
}
Copied!

Responses

  • Success: HTTP 200 with an array of balances
  • Bad data: HTTP 404 with error message
    • eg. not found

Create User Membership

POST /users/:auth_id/memberships
All fields are mandatory.
Each user can have 1 membership per exchange provider. You can override the membership number in specific requests - for example, when exchanging points to miles you can provide a new membership number specifically for that request.
exchange_provider_implementation_name can be one of:
  • etihad
  • miles_and_more
The membership number will be validated. If you want to know how you can validate the numbers yourself please reach out to us and we will provide the algorithms for each exchange provider.
eg.
1
{
2
"membership": {
3
"exchange_provider_implementation_name": "etihad" | "miles_and_more",
4
"membership_number": "xxxx....xxx"
5
}
6
}
Copied!

Responses

  • Created: HTTP 201 with the user object
  • Not found: HTTP 404
    • user not found
  • Bad data: HTTP 400 with error message
    • invalid format for the membership number
    • invalid exchange provider

Update User Membership

Same as Create User Membership.

Get User Memberships

GET /users/:auth_id/memberships
This will return all the memberships for a user. If no memberships exist for the user this will be an empty array.
eg.
1
{
2
"data": [
3
{
4
"membership_number": "xxx...xxxx",
5
"exchange_provider": {
6
"name": "Miles and More",
7
"implementation_name": "miles_and_more"
8
}
9
},
10
{
11
"membership_number": "yyy...yyyy",
12
"exchange_provider": {
13
"name": "Etihad",
14
"implementation_name": "etihad"
15
}
16
}
17
]
18
}
Copied!

Get User Membership

GET /users/:auth_id/memberships/:implementation_name
Returns the membership information for a user for a particular exchange provider implementation, if found, 404 and empty object otherwise.
eg.
1
{
2
"data": {
3
"membership_number": "xxx...xxx",
4
"exchange_provider": {
5
"implementation_name": "etihad",
6
"name": "Etihad"
7
}
8
}
9
}
Copied!
Responses
  • Success: HTTP 200 with membership
  • Not found: HTTP 404 if user or membership not found

Delete User Membership

DELETE /users/:auth_id/memberships/:implementation_name
Deletes the membership information for a user if it exists. Returns 404 if user or membership not found.
eg.
1
{
2
"data": {
3
"membership_number": "xxx...xxx",
4
"exchange_provider": {
5
"implementation_name": "etihad",
6
"name": "Etihad"
7
}
8
}
9
}
Copied!
Responses
  • Success: HTTP 204
  • Not found: HTTP 404 if user or membership not found
  • Bad request: HTTP 400 if the implementation does not exist

Codes

Use this set of endpoints to manage codes that can be given out to users for points or external rewards like airline FFP miles.

Create Code

POST /codes
Create a new code.
We will give you all your campaign_id values.
Fields:
  • value - value of points the code is worth
    • The external reward rate will be calculated based on your settings.
    • eg. if 1 point is 10 miles, then a code of 5 points is worth 50 miles.
  • campaign_id - all the IDs for your campaigns will be provided by us
  • length - optional. Length of the code to generate.
    • Minimum: 9
    • Default: 9
  • email - optional. If an email is passed we will also send the user an email with the code generated. You can choose a template or make a new one. Defaults to null
  • language - optional. Language for the email. Defaults to en
  • reference_id - optional. type: string.
    • is used as a duplicate check, so if it's sent it always needs to be unique for every request.
    • For example, you could pass your internal receipt/order ID to make sure that one transaction in your system is never processed twice, even if you happen to send the request twice.
eg.
1
{
2
"code": {
3
"value": "100",
4
"campaign_id": 1,
5
"language": "en",
6
"reference_id": "Order 109348HJ61"
7
}
8
}
Copied!
Responses:
  • Success: HTTP 201 and the code:
    • 1
      {
      2
      "data": {
      3
      "code": "719026461",
      4
      "value": "100",
      5
      "campaign_id": 1,
      6
      "reference_id": "Order 109348HJ61"
      7
      }
      8
      }
      Copied!
  • Bad request: HTTP 400
    • eg. Invalid campaign id or Code length too short
  • Conflict: HTTP 409 when reference_id was already used

Rewards

Manage your rewards. Eg. Discount Coupons
Users exchange points for a reward.
Soon you will also be able to send rewards to users dynamically.

Get Reward Details

GET /rewards/:reward
This endpoint will fetch a reward and the associated transaction, used_at, anduser_id if it has already been sent to a user.
Check out the Transactions section of the documentation to see what the loyalty event types are.
Responses:
  • Success: HTTP 200 with data in the following format:
1
{
2
"data": {
3
"code": "testcode29",
4
"reward_type": {
5
"id": 1,
6
"locations": [
7
{
8
"id": "2039",
9
"street": "Falkenstrasse",
10
"city": "Zurich",
11
"country": "Switzerland",
12
"zip": "8008",
13
"geolocation": "Geolocation point"
14
}
15
],
16
"metadata": {
17
"coverImage": "https://picsum.photos/id/1025/200/300"
18
},
19
"name": "Online Coupon",
20
"valid_until": "2021-11-23T15:19:19Z",
21
"value": 5,
22
"website": "https://qiibee.com/?extralong_link=verylonglink"
23
},
24
"transaction": {
25
"amount_received": 20,
26
"code": null | "GDUTY5F",
27
"exchange_provider": "etihad" | "miles_and_more",
28
"id": 562,
29
"inserted_at": "2021-08-10T15:53:25",
30
"loyalty_event_type": "points_to_rewards",
31
"points_burned": 5,
32
"reward_id": 29,
33
"status": "success",
34
"token": null | {
35
"id": "23421",
36
"address": "0x..3849hz654",
37
"name": "My Token Name",
38
"type": "erc20" | "erc721",
39
"metadata": {
40
"key": "value"
41
}
42
43
},
44
"tx_hash": "0x.......293dsf23"
45
"used_at": null | "2021-09-28T14:57:49Z",
46
"user": null | {
47
"id": "3r2esf3423r",
48
"email": "[email protected]",
49
"auth_id": "e24c962d-c81c-4a01-b0cd-57dd233553f1",
50
"first_name": "John",
51
"second_name": "Doe",
52
"language": "en",
53
"country_ISO": "usa"
54
}
55
}
56
}
Copied!
  • Bad data: HTTP 404 with error message
    • eg. not found

Redeem a Reward

PUT /rewards/:reward | PATCH /rewards/:reward
This endpoint is used to mark a reward as used.
We mark it as used by setting the used_at property to the UTC time of the request.
Currently, each reward can be used only once.

Responses

  • Success: HTTP 200 with data in the following format:
1
{
2
"code": "SPECIAL20",
3
"used": true,
4
"user": {
5
"id": "3253124153214",
6
"auth_id": "e24c962d-c81c-4a01-b0cd-57dd233553f1",
7
"first_name": "Jane",
8
"second_name": "Doe",
9
"email": "[email protected]",
10
"language": "en",
11
"country_ISO": "usa"
12
},
13
"reward_type": {
14
"id": 10,
15
"name": "20 EUR Discount",
16
"value": "100",
17
"website": "www.domain.com",
18
"valid_until": "1659515347",
19
"locations": [
20
{
21
"id": "2039",
22
"street": "Falkenstrasse",
23
"city": "Zurich",
24
"country": "Switzerland",
25
"zip": "8008",
26
"geolocation": "Geolocation point"
27
}
28
]
29
},
30
"transaction": {
31
"id": "284798327469",
32
"loyalty_event_type": "points_to_rewards",
33
"exchange_provider": "etihad" | "miles_and_more",
34
"tx_hash": "0x.......293dsf23",
35
"points_burned": "100",
36
"token": null | {
37
"id": "23421",
38
"address": "0x..3849hz654",
39
"name": "My Token Name",
40
"type": "erc20" | "erc721",
41
"metadata": {
42
"key": "value"
43
}
44
},
45
"status": "success",
46
"reward_id": 3443,
47
"inserted_at": "1627976023"
48
}
49
}
Copied!
  • Conflict: HTTP 409
    • If the reward was already marked as used
  • Bad data: HTTP 404 with error message
    • eg. not found

Transactions

The following transaction/loyalty event types exist and you can use the transactions API to perform actions:
  • code_to_points - redeem a code for points
  • code_to_nft - redeem a code for an NFT
  • code_to_external_rewards - redeem a code for external rewards like miles
  • credit_points - credit point's to a user's account
    • eg. reward a user for spends
  • debit_points - debit points from a user's account
    • eg. redeem points for a reward like a coupon
  • points_to_rewards - redeem points for a reward like a discount coupon
  • points_to_external_rewards - redeem points for external rewards like miles
  • nft_personalisation - approve/reject a user's NFT personalisation
    • controlled via the NFTs endpoint

Create Transaction

POST /transactions
Use this endpoint to create any of the transaction types listed below.
Currently supported:
  • credit_points
  • debit_points
  • points_to_rewards
  • points_to_external_rewards
Based on the transaction type the body will differ.

Credit/Debit Points

All fields are mandatory.
If you try to debit more points than the user currently has you'll receive a 400.
Body:
  • amount can be an integer or string. Must be greater than 0.
  • send_email (optional) can be used only for type credit_points
    • Defaults: false.
1
{
2
"transaction": {
3
"user_auth_id": "d0d15b76-1928-46bb-9927-8ffbf802455f",
4
"type": "credit_points" | "debit_points",
5
"amount": "100",
6
"token_id": 12,
7
"send_email": true | false
8
}
9
}
Copied!

Responses

  • Accepted: HTTP 202 If send_email has been set to true, the email will be sent to the registered email ID of the user with user_auth_id .
  • Bad Request: HTTP 400
    • eg. unknown transaction type
  • Bad data: HTTP 404 with error message
    • eg. not found

Exchange Points to Rewards

All fields are mandatory.
If you try to exchange more points than the user currently has you'll receive a 400.
Body:
  • amount can be an integer or string.
1
{
2
"transaction": {
3
"user_auth_id": "d0d15b76-1928-46bb-9927-8ffbf802455f",
4
"type": "points_to_rewards",
5
"amount": "100",
6
"token_id": 12,
7
"reward_type_id": 2432
8
}
9
}
Copied!

Exchange Points to External Rewards

The following fields are optional:
  • membership_number_override- string - use this field to override the user's saved membership number only for this action
    • It will not overwrite the saved number in the account
  • exchange_rate_override- integer - use this field to specify a different exchange rate from what you've configured.
    • eg. 1 point is 40 airline miles but you want to change it to 80 for a particular user based on their tier.
    • It will not overwrite the stored exchange rate
If you do not want to persist membership info for users you can send it with every request but for a better customer experience, we encourage you to store it using the memberships API.
If you try to exchange more points than the user currently has you'll receive a 400.
Body:
  • amount can be an integer or string.
1
{
2
"transaction": {
3
"user_auth_id": "d0d15b76-1928-46bb-9927-8ffbf802455f",
4
"type": "points_to_external_rewards",
5
"amount": "100",
6
"token_id": 12,
7
"exchange_provider_implementation_name": "etihad" | "miles_and_more",
8
"membership_number_override": "xxx...xxx",
9
"exchange_rate_override": "10"
10
}
11
}
Copied!
Responses
  • Success: HTTP 202
  • Bad request: HTTP 400
    • Insufficient balance
    • Invalid amount field
    • User/Token does not exist
    • Non existent exchange provider
    • Invalid membership number

Transaction History

GET /transactions
This request returns paginated transaction history.
By default, it returns the last 100 transactions associated with your brand. The most recent transactions are returned first.
You can query transactions using the following query parameters:
  • limit: (optional) sets the required limit of transaction history to be requested.
    • Defaults: 100
    • Maximum: 100
  • offset: (optional) sets the number of transactions to be ignored before the relevant transactions can be returned.
    • Default: 0
  • user_auth_id: (optional) Use this parameter to query transactions for a particular user of your brand. If not passed returns all the transactions for your brand. Can be used along with limit and offset
The params limit and offset work exactly as they’re used in SQL.

Responses

  • Success: HTTP 200 with data in the following format:
1
{
2
"data": {
3
"limit": 1,
4
"offset": 0,
5
"total_tx_count": 25,
6
"transactions": [
7
{
8
"amount_received": 1,
9
"code": null,
10
"exchange_provider": "etihad" | "miles_and_more",
11
"id": 706,
12
"inserted_at": "2021-09-27T14:31:10",
13
"loyalty_event_type": "credit_points",
14
"points_burned": null,
15
"reward_id": null,
16
"status": "success",
17
"token": {
18
"id": "3276728",
19
"address": "033Bd49F3ace247112AA6D3d16d24F7Eb5533b17",
20
"metadata": {},
21
"name": "WORKING POINT TOKEN",
22
"type": "erc20" | "erc721"
23
},
24
"tx_hash": "0x..xx26"
25
}
26
]
27
}
28
}
Copied!
If there are no transactions, an empty transactions list will be returned. total_tx_count is the total number of transactions available for the given params.
  • Bad data: HTTP 404 with error message
    • eg. not found

NFTs

Manage your NFTs and approve/reject user personalisations like engravings and personal messages.

Approve/Reject NFT personalisation

POST /nfts
Use this endpoint to approve or reject a user's NFT personalisation.
If you reject it, the user will receive an email asking them to change the personalisation. You can pick from existing mail templates or create a new one.
All fields are mandatory.
eg.
1
{
2
"userNFT": {
3
"user_nft_id": "37329",
4
"status": "approved" | "rejected"
5
}
6
}
Copied!
Last modified 27d ago