Zwing Docs

GV Service

Documentation for GV Service module in G1 CRM.

Gift Voucher (GV) Service API Documentation

Overview

The GV Service manages creation, sale, allocation, redemption, and import of Gift Vouchers (physical and e-GVs). It uses MongoDB for persistence and Redis for cart/session/verification and throttling. All routes are protected with permission-based guards unless explicitly skipped.

There are 2 types of gvs.

  1. Physical GV
  2. E-GV

Physical GV

Physical GV's are created before selling and is allocated to stores.

E-GV

E-GV are created at the time of selling but it's allocation are provided on each store bases like how many EGV a store can create and sell. This restrictions get refreshed on time to time bases as set in the gv group (i.e every day, week, month).

Pack:

Packs are logical booklet which has GV's. it's like bunch of gv inside single pack. while creating a group you can mention if you want to create a pack or not. (note: only physical gv can have the pack.)

Prerequisites

  1. Enterprise, Apps (POS/Web), Stores configured in CRM
  2. Authentication via SSO/App and Bearer token
  3. Proper permissions granted to caller (see each endpoint)
  4. Transaction Format (Common Module)

Base URL (Staging)

https://api.dev-engage.ginesys.one/gv/v1/

Authentication

Authorization: Bearer <token>
x-tenant-id: <tenantId>

Common Headers

  • x-tenant-id (string, required)
  • Authorization (string, required) Bearer token

Important Notes

  1. Carts and some verifications expire automatically in Redis (generally 15–20 minutes windows)
  2. Physical GV sale validates allocation to store/app and voucher status
  3. EGV sale respects group/channel sale limits and generates on demand
  4. Redemption honors verification type (None/Pin/OTP), redemption channels, and partial redemption policy
  5. Most list/get APIs support include to enrich payloads

System Components

  • Database: MongoDB via repositories under @libs/gv, @libs/common, @libs/cdp, @libs/butler
  • Cache: Redis via @libs/intent/cache with keys from @libs/gv and @libs/common
  • Queue/Notifications: @libs/intent/queue and CommonLib notifications for OTP/PIN and redemption events

Transaction Format APIs

All routes guarded by PermissionGuard.

Transaction format are basically kind of unique ids which are configured for specific gv groups.

Each Group will have one transaction id associated to it for creation of the gvNo.

List Transaction Format

POST common/v1/transaction-formats/list
Permission: 'gift-voucher-group::list', 'transaction-format::list'
Includes: audits
Supports: search. sorting, advanceFilters
  • Logic: Will List all the transaction format.

Request (example):

curl --location 'https://api.dev-engage.ginesys.one/common/v1/transaction-formats/list?page=1&perPage=1' \
--header 'x-tenant-id: <id>' \
--header 'Authorization: Bearer <token>'

Param:

page: 1
perPage: 10

Response:

{
  "status": 200,
  "success": true,
  "data": [
    {
      "id": "690461d30886f3fa617abcd6",
      "name": "Doc",
      "type": "gift-voucher",
      "isSystemGenerated": false,
      "preview": "DCA250001JYXASF",
      "associationRefId": "6904571ea5e00a3a761d8628",
      "status": "in-use",
      "pattern": [
        {
          "index": 0,
          "type": "fix-text",
          "value": "DC"
        },
        {
          "index": 1,
          "type": "date",
          "dateType": "month",
          "dateFormat": "MYY",
          "isFinancialYear": false,
          "value": "A25"
        },
        {
          "index": 2,
          "type": "sequence",
          "value": "0001",
          "sequenceId": "690461d30886f3fa617abcd4",
          "length": 4
        },
        {
          "index": 3,
          "type": "random",
          "value": "GI23",
          "length": 4
        },
        {
          "index": 4,
          "type": "fix-text",
          "value": "SF"
        }
      ]
    }
  ],
  "meta": {
    "pagination": {
      "perPage": 1,
      "currentPage": 1,
      "total": 469,
      "totalPages": 469
    }
  }
}

Create Transaction Format

POST common/v1/transaction-formats
Permission: 'gift-voucher-group::create', 'gift-voucher-group::update','transaction-format::create',
Includes: audits

Logic:

  • Will check if Tf with same pattern exist or not.
  • Will validate the pattern and create the transaction format.

Request (example):

curl --location 'https://api.dev-engage.ginesys.one/common/v1/transaction-formats' \
--header 'x-tenant-id: <id>' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token>' \
--data '{
    "name": "Doc 123",
    "type": "gift-voucher",
    "pattern": [
        {
            "index": 0,
            "type": "fix-text",
            "value": "DO"
        },
        {
            "index": 1,
            "type": "date",
            "value": "2425",
            "dateFormat": "YYYY",
            "dateType": "year",
            "isFinancialYear": true
        },
        {
            "index": 2,
            "type": "sequence",
            "value": "0001",
            "length": 4
        },
        {
            "index": 3,
            "type": "random",
            "value": "GI23",
            "length": 4
        },
        {
            "index": 4,
            "type": "fix-text",
            "value": "1T"
        }
    ],
    "startSequence": 1
}'

Param:

{
  "name": "Doc 123",
  "type": "gift-voucher",
  "pattern": [
    {
      "index": 0,
      "type": "fix-text",
      "value": "DO"
    },
    {
      "index": 1,
      "type": "date",
      "value": "2425",
      "dateFormat": "YYYY",
      "dateType": "year",
      "isFinancialYear": true
    },
    {
      "index": 2,
      "type": "sequence",
      "value": "0001",
      "length": 4
    },
    {
      "index": 3,
      "type": "random",
      "value": "GI23",
      "length": 4
    },
    {
      "index": 4,
      "type": "fix-text",
      "value": "1T"
    }
  ],
  "startSequence": 1
}

Response:

{
  "status": 200,
  "success": true,
  "data": {
    "id": "69049a7e0886f3fa617abd2e",
    "name": "Doc 123",
    "type": "gift-voucher",
    "isSystemGenerated": false,
    "preview": "DO25260001XHE11T",
    "status": "unused",
    "pattern": [
      {
        "index": 0,
        "type": "fix-text",
        "value": "DO"
      },
      {
        "index": 1,
        "type": "date",
        "dateType": "year",
        "dateFormat": "YYYY",
        "isFinancialYear": true,
        "value": "2425"
      },
      {
        "index": 2,
        "type": "sequence",
        "value": "0001",
        "sequenceId": "69049a7e0886f3fa617abd2c",
        "length": 4
      },
      {
        "index": 3,
        "type": "random",
        "value": "GI23",
        "length": 4
      },
      {
        "index": 4,
        "type": "fix-text",
        "value": "1T"
      }
    ]
  }
}

Update Transaction Format

PUT common/v1/transaction-formats
Permission: 'gift-voucher-group::update', 'transaction-format::update',
Includes: audits

Logic:

  • Will check if Tf with same pattern exist or not.
  • Will validate the pattern and create the transaction format.

Request (example):

curl --location --request PUT 'https://api.dev-engage.ginesys.one/common/v1/transaction-formats' \
--header 'x-tenant-id: <id>' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token>' \
--data '{
    "id": "69049a7e0886f3fa617abd2e",
    "name": "Doc 123",
    "type": "gift-voucher",
    "pattern": [
        {
            "index": 0,
            "type": "fix-text",
            "value": "DO"
        },
        {
            "index": 1,
            "type": "date",
            "value": "2425",
            "dateFormat": "YYYY",
            "dateType": "year",
            "isFinancialYear": true
        },
        {
            "index": 2,
            "type": "sequence",
            "value": "0001",
            "length": 4
        },
        {
            "index": 3,
            "type": "random",
            "value": "GI23",
            "length": 4
        },
        {
            "index": 4,
            "type": "fix-text",
            "value": "1T"
        }
    ],
    "startSequence": 1
}'

Param:

{
  "id": "69049a7e0886f3fa617abd2e",
  "name": "Doc 123",
  "type": "gift-voucher",
  "pattern": [
    {
      "index": 0,
      "type": "fix-text",
      "value": "DO"
    },
    {
      "index": 1,
      "type": "date",
      "value": "2425",
      "dateFormat": "YYYY",
      "dateType": "year",
      "isFinancialYear": true
    },
    {
      "index": 2,
      "type": "sequence",
      "value": "0001",
      "length": 4
    },
    {
      "index": 3,
      "type": "random",
      "value": "GI23",
      "length": 4
    },
    {
      "index": 4,
      "type": "fix-text",
      "value": "1T"
    }
  ],
  "startSequence": 1
}

Response:

{
  "status": 200,
  "success": true,
  "data": {
    "id": "69049a7e0886f3fa617abd2e",
    "name": "Doc 123",
    "type": "gift-voucher",
    "isSystemGenerated": false,
    "preview": "DO25260001TDA21T",
    "status": "unused",
    "pattern": [
      {
        "index": 0,
        "type": "fix-text",
        "value": "DO"
      },
      {
        "index": 1,
        "type": "date",
        "dateType": "year",
        "dateFormat": "YYYY",
        "isFinancialYear": true,
        "value": "2425"
      },
      {
        "index": 2,
        "type": "sequence",
        "value": "0001",
        "sequenceId": "69049b9e0886f3fa617abd34",
        "length": 4
      },
      {
        "index": 3,
        "type": "random",
        "value": "GI23",
        "length": 4
      },
      {
        "index": 4,
        "type": "fix-text",
        "value": "1T"
      }
    ]
  }
}

Validate Transaction Format

POST common/v1/transaction-formats/validate
Permission: 'gift-voucher-group::create',
'gift-voucher-group::update',
'transaction-format::create',

Logic:

  • Will check if Tf with same pattern exist or not.
  • Will validate the pattern and create the transaction format.

Request (example):

curl --location 'https://api.dev-engage.ginesys.one/common/v1/transaction-formats/validate' \
--header 'x-tenant-id: <id>' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token>' \
--data '{
    "name": "doc-2",
    "type": "gift-voucher",
    "pattern": [
        {
            "index": 0,
            "type": "fix-text",
            "value": "DO"
        },
        {
            "index": 1,
            "type": "date",
            "value": "2425",
            "dateFormat": "YYYY",
            "dateType": "year",
            "isFinancialYear": true
        },
        {
            "index": 2,
            "type": "sequence",
            "value": "0001",
            "length": 4
        },
        {
            "index": 3,
            "type": "random",
            "value": "GI23",
            "length": 4
        },
        {
            "index": 4,
            "type": "fix-text",
            "value": "1T"
        }
    ],
    "startSequence": 1
}'

Body:

{
  "name": "doc-2",
  "type": "gift-voucher",
  "pattern": [
    {
      "index": 0,
      "type": "fix-text",
      "value": "DO"
    },
    {
      "index": 1,
      "type": "date",
      "value": "2425",
      "dateFormat": "YYYY",
      "dateType": "year",
      "isFinancialYear": true
    },
    {
      "index": 2,
      "type": "sequence",
      "value": "0001",
      "length": 4
    },
    {
      "index": 3,
      "type": "random",
      "value": "GI23",
      "length": 4
    },
    {
      "index": 4,
      "type": "fix-text",
      "value": "1T"
    }
  ],
  "startSequence": 1
}

Response:

{
  "status": 200,
  "success": true,
  "data": {
    "isDuplicate": true,
    "isNameDuplicate": false,
    "warnings": [
      "Sequence will reset every year based on date format",
      "Sequence can have maximum of 9999 unique transaction number every year"
    ],
    "length": 16,
    "maxPossibleNo": 16796160000
  }
}

Available Sequence

POST common/v1/transaction-formats/:id/available-sequence
Permission: 'gift-voucher::get', 'transaction-format::get'

Logic:

  • will give the total available sequence.

Request (example):

curl --location 'https://api.dev-engage.ginesys.one/common/v1/transaction-formats/67a9ada8581a7a0177e86f0d/available-sequence' \
--header 'x-tenant-id: <id>' \
--header 'Authorization: Bearer <token>'

Response:

{
  "status": 200,
  "success": true,
  "data": {
    "isSequenceAvailable": true,
    "count": 9987
  }
}

Get Transaction Format

POST common/v1/transaction-formats/:id
Permission: 'gift-voucher::get', 'transaction-format::get'

Logic:

  • will give the existing transaction format.

Request (example):

curl --location 'https://api.dev-engage.ginesys.one/common/v1/transaction-formats/67a9ada8581a7a0177e86f0d?include=audits' \
--header 'x-tenant-id: <id>' \
--header 'Authorization: Bearer <token>'

Response:

{
  "status": 200,
  "success": true,
  "data": {
    "id": "67a9ada8581a7a0177e86f0d",
    "name": "Secureexchange555483",
    "type": "gift-voucher",
    "isSystemGenerated": false,
    "preview": "OB0012",
    "associationRefId": "6904726f8487a84bc0e17be5",
    "status": "in-use",
    "pattern": [
      {
        "index": 0,
        "type": "fix-text",
        "value": "OB"
      },
      {
        "index": 1,
        "type": "sequence",
        "value": "0012",
        "sequenceId": "67a9ada8581a7a0177e86f0b",
        "length": 4
      }
    ],
    "audits": {
      "createdAt": "2025-02-10T07:41:28.123Z",
      "updatedAt": "2025-10-31T09:01:09.416Z",
      "createdById": "665d43fa8b49af2a7c506ada",
      "createActor": "Akshay P"
    }
  }
}

Categories APIs (categories)

All routes guarded by PermissionGuard.

A Category is used to group multiple GV groups under a single tag. By creating a category, you can organize and tag specific GV groups together for better management.

Create Category

POST /categories
Permission: gv-category -> create
  • Logic: Checks if the Category Exists on the same name or refId and throws error otherwise Creates GV Category

Request (example):

curl 'https://api.dev-engage.ginesys.one/gv/v1/categories' \
  -H 'Content-Type: application/json' \
  -H 'authorization: Bearer <token>' \
  -H 'x-tenant-id: <tenantId>' \
  --data-raw '{"name":"Jinendra"}'

Body:

{
"name": "Jinendra", (string, required)
"refId": "CAT1" (string, optional)
}

Response:

{
  "status": 200,
  "success": true,
  "data": {
    "id": "69044caea5e00a3a761d8608",
    "name": "jinendra"
  }
}

List Categories

GET /categories
Permission: gv-category -> list
include: audit
  • Logic: Paginated search

Request (example):

curl 'https://api.dev-engage.ginesys.one/gv/v1/categories?queryFilter=page=1&perPage=100' \
  -H 'authorization: Bearer <token>' \
  -H 'x-tenant-id: <tenantId>'

Query parameters (via queryFilter):

  • page (number, default 1)
  • perPage (number, default 10)
  • include (string, optional)

Response:

{
  "status": 200,
  "success": true,
  "data": [
    { "id": "68907c692ee363f7f7a3a531", "name": "demo-101" },
    { "id": "67a323c872752eeaff79e1fe", "name": "physical" }
  ],
  "meta": {
    "pagination": {
      "perPage": 100,
      "currentPage": 1,
      "total": 21,
      "totalPages": 1
    }
  }
}

Delete Category

DELETE /categories/:id
Permission: gv-category -> delete
  • Logic: If category is in use by any gv group it will throw an error otherwise Soft delete.

Configs APIs (configs)

All routes guarded by PermissionGuard.

Create Config

POST /configs
Permission: gv-config::create
Body: GVConfigDto
  • Logic: Creates GV configuration (redemption, multiple GV limits, verification type)
  • DB: gvConfigRepo.new(...)
  • Cache: none

List Configs

GET /configs
Permission: gv-config::list
Support: Search, Filters, AdvanceFilters, Sorting
Include: audits
  • Logic: Paginated search
curl --location 'http://localhost:5001/gv/v1/configs' \
--header 'x-tenant-id: <tenantId>' \
--header 'Authorization: Bearer <token>'
{
  "status": 200,
  "success": true,
  "data": [
    {
      "id": "67a08d2f72752eeaff79d06c",
      "name": "Dsfg",
      "description": "esdhgjkl",
      "allowPartialRedemption": true,
      "allowMultipleGVInSingleInvoice": false,
      "allowReturn": true,
      "authenticationType": "pin",
      "gvAllowedInSingleInvoice": 0,
      "audits": {
        "createdAt": "2025-02-03T09:32:31.160Z",
        "updatedAt": "2025-02-03T09:32:31.160Z",
        "createdById": "665d43fa8b49af2a7c506ada",
        "createActor": "665d43fa8b49af2a7c506ada"
      }
    },...
  ],
  "meta": {
    "pagination": {
      "perPage": 10,
      "currentPage": 1,
      "total": 302,
      "totalPages": 31
    }
  }
}

Update Config

PUT /configs
Permission: gv-config::update
Include: audits
  • Logic:
    • Checks if the Config is Available or not.
    • Checks if config is being used already in the group.
    • if yes can't allow to edit and throws error.
    • if no Updates config
curl --location --request PUT 'https://api.dev-engage.ginesys.one/gv/v1/configs?include=audits' \
--header 'x-tenant-id: <tenantId>' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token>' \
--data '{
    "id": "69045338a5e00a3a761d8614",
    "name": "Demo Config",
    "description": "Something meaningful description of this GV Group",
    "allowPartialRedemption": false,
    "allowMultipleGVInSingleInvoice": false,
    "allowReturn": true,
    "verificationType": "pin",
    "gvAllowedInSingleInvoice":10
}'

Body:

{
  "id": "69045338a5e00a3a761d8614",
  "name": "Demo Config",
  "description": "Something meaningful description of this GV Group",
  "allowPartialRedemption": false,
  "allowMultipleGVInSingleInvoice": false,
  "allowReturn": true,
  "verificationType": "pin",
  "gvAllowedInSingleInvoice": 10
}

Response :

{
  "status": 200,
  "success": true,
  "data": {
    "id": "69045338a5e00a3a761d8614",
    "name": "Demo Config",
    "description": "Something meaningful description of this GV Group",
    "allowPartialRedemption": false,
    "allowMultipleGVInSingleInvoice": false,
    "allowReturn": true,
    "authenticationType": "pin",
    "gvAllowedInSingleInvoice": 10,
    "audits": {
      "createdAt": "2025-10-31T06:12:08.417Z",
      "updatedAt": "2025-10-31T06:12:44.454Z",
      "createdById": "665d43fa8b49af2a7c506ada",
      "updatedById": "665d43fa8b49af2a7c506ada",
      "createActor": "Akshay P",
      "updateActor": "Akshay P"
    }
  }
}

Groups APIs (groups)

Routes guarded by PermissionGuard and GvRefIdGuard.

Create Group

POST /groups
Permission: gift-voucher-group -> create

pre-requisite:

  • To create a gv group we will need gv category, gv config, store cluster created on crm, app connected to crm and transaction format.

Logic:

  • gv group can be for Egv or Physical gv.

  • gv group can have packs. but egv don't have the packs. (optional)

  • gv group has multiple validity optional like limitedTime and lifetime.

  • inside limited time you can choose effective date and validity type

  • In lifetime validity you can only select the effective date as there is no expiry.

  • effective date can be custom date from current date or voucher sales date.

  • There are 2 types of validity custom date and period.

  • In the period you can select the days of periods from the effective date.

  • After the validity date / period voucher inside the group can't be sold or redeemed.

  • There are 2 types of denominations dynamic and fixed.

  • Fixed denomination states the fixes gift value and sale value

  • Dynamic denomination states the gift value percentage of sale value. Means Sale value will be calculated on the bases of gift value and provided denomination percentage of the gift value. dynamic denomination will only have the min value, max value and sales Percentage.

  • validates config, category, denominations, type, validity, transaction format, etc.

Validity:

Life Time with Sales Date

"validity": {
 "type": "lifetime",
 "effectiveFrom": {
 "type": "sales-date"
 }
}

Life Time With Custom Date

"validity": {
 "type": "lifetime",
 "effectiveFrom": {
 "type": "calendar-date",
 "date": "2025-10-31T08:22:11.502Z"
 }
}

Limited Time With Effective and Validity Custom Date

"validity": {
 "type": "limited-time",
 "effectiveFrom": {
 "type": "calendar-date",
 "date": "2025-10-31T08:22:11.502Z"
 },
 "expiry": {
     "type": "calendar-date",
     "date": "2025-11-29T18:30:00.000Z",
 },
},

Limited Time With Effective Custom Date and Validity In Period

"validity": {
 "type": "limited-time",
 "effectiveFrom": {
 "type": "calendar-date",
 "date": "2025-10-31T08:22:11.502Z"
 },
 "expiry": {
     "type": "period",
     "days": 365,
 },
},

From the above examples you can create multiple combinations.

Dynamic and Fixed Denomination

[
    {
        "type": "dynamic-value",
        "name": "Doc 2",
        "minGiftValue": 100,
        "maxGiftValue": 1000,
        "saleValuePercentageGiftValue": 100
    },
    {
        "type": "fix-value",
        "name": "Doc 1",
        "giftValue": 10,
        "saleValue": 10,
    }
]
curl --location 'https://api.dev-engage.ginesys.one/gv/v1/groups' \
--header 'x-tenant-id: <id>' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token>' \
--data '{
    "name": "Demo Documentation group",
    "description": "test",
    "categoryId": "69044caea5e00a3a761d8608",
    "type": "egv",
    "validity": {
        "type": "limited-time",
        "effectiveFrom": {
            "type": "calendar-date",
            "date": "2025-12-18T18:30:00.000Z"
        },
        "expiry": {
            "type": "period",
            "date": "",
            "days": 2,
            "tempDays": "2",
            "period": "day"
        }
    },
    "createPack": false,
    "denominations": [
        {
            "type": "fix-value",
            "name": "d1",
            "giftValue": 10,
            "saleValue": 20
        }
    ],
    "redemptionChannels": [{"appId": "665d43f48b49af2a7c5048aa", "clusterIds": ["679dc39e4d5bc083264ef9db"]}],
    "configId": "69045338a5e00a3a761d8614",
    "storesList": [],
    "transactionFormatId": "67add88ba3137a721e4a1fcf"
}'

Body:

{
  "name": "Demo Documentation group",
  "description": "test",
  "categoryId": "69044caea5e00a3a761d8608",
  "type": "egv",
  "validity": {
    "type": "limited-time",
    "effectiveFrom": {
      "type": "calendar-date",
      "date": "2025-12-18T18:30:00.000Z"
    },
    "expiry": {
      "type": "period",
      "date": "",
      "days": 2,
      "tempDays": "2",
      "period": "day"
    }
  },
  "createPack": false,
  "denominations": [
    {
      "type": "fix-value",
      "name": "d1",
      "giftValue": 10,
      "saleValue": 20
    }
  ],
  "redemptionChannels": [
    {
      "appId": "665d43f48b49af2a7c5048aa",
      "clusterIds": ["679dc39e4d5bc083264ef9db"]
    }
  ],
  "configId": "69045338a5e00a3a761d8614",
  "storesList": [],
  "transactionFormatId": "67add88ba3137a721e4a1fcf",
  "imageSlug": "path to blob" (optional)
}

Response:

{
  "status": 200,
  "success": true,
  "data": {
    "id": "6904571ea5e00a3a761d8628",
    "name": "Demo Documentation Group",
    "systemId": "GVG7358",
    "description": "test",
    "redemptionChannels": [
      {
        "appId": "665d43f48b49af2a7c5048aa",
        "clusterIds": ["679dc39e4d5bc083264ef9db"]
      }
    ],
    "status": "voucher-not-created",
    "type": "egv",
    "categoryId": "69044caea5e00a3a761d8608",
    "validity": {
      "type": "limited-time",
      "effectiveFrom": {
        "type": "calendar-date",
        "date": "2025-12-18T18:30:00.000Z"
      },
      "expiry": {
        "type": "period",
        "date": null,
        "days": 2
      },
      "expiryDate": "2025-12-20T18:30:00.000Z"
    },
    "createPack": false,
    "transactionFormatId": "67add88ba3137a721e4a1fcf",
    "isActive": true,
    "stopSales": false
  }
}

Update Group

PATCH /groups
Permission: gift-voucher-group -> update

Logic:

  • if the vouchers are not generated or imported in the group it can be updated. all the validation performed on the create api are being done in the update as well.
  • if stopSales is send as true. all the voucher inside the group will not be allows to sell.
curl --location --request PATCH 'https://api.dev-engage.ginesys.one/gv/v1/groups' \
--header 'x-tenant-id: <id>' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token>' \
--data '{
    "id": "6904571ea5e00a3a761d8628",
    "name": "Demo Documentation group",
    "description": "Test Import",
    "redemptionChannels": [],
    "type": "physical-gv",
    "categoryId": "69044caea5e00a3a761d8608",
    "validity": {
        "type": "limited-time",
        "effectiveFrom": {
            "type": "sales-date",
            "date": "2025-01-03T10:53:26.035Z"
        },
        "expiry": {
            "type": "calendar-date",
            "date": "2025-01-03T10:52:31.000Z",
            "days": null,
            "period": "year"
        },
        "expiryDate": "2025-01-03T10:52:31.000Z"
    },
    "createPack": true,
    "transactionFormatId": "6777ad3f42b0b29b9a92c796",
    "isActive": true,
    "stopSales": false,
    "denominations": [
        {
            "type": "fix-value",
            "name": "d1",
            "giftValue": 10,
            "saleValue": 20
        }
    ],
     "configId": "69045338a5e00a3a761d8614"
}'

Body:

{
  "id": "6904571ea5e00a3a761d8628",
  "name": "Demo Documentation group", (optional)
  "description": "Test Import", (optional)
  "redemptionChannels": [], (optional)
  "type": "physical-gv", (optional)
  "categoryId": "69044caea5e00a3a761d8608", (optional)
  "validity": {
    "type": "limited-time",
    "effectiveFrom": {
      "type": "sales-date",
      "date": "2025-01-03T10:53:26.035Z"
    },
    "expiry": {
      "type": "calendar-date",
      "date": "2025-01-03T10:52:31.000Z",
      "days": null,
      "period": "year"
    },
    "expiryDate": "2025-01-03T10:52:31.000Z"
  }, (optional)
  "createPack": true, (optional)
  "transactionFormatId": "6777ad3f42b0b29b9a92c796", (optional)
  "isActive": true,(optional)
  "stopSales": false,(optional)
  "denominations": [
    {
      "type": "fix-value",
      "name": "d1",
      "giftValue": 10,
      "saleValue": 20
    }
  ],(optional)
  "configId": "69045338a5e00a3a761d8614"(optional)
}

Response:

{
  "status": 200,
  "success": true,
  "data": {
    "id": "6904571ea5e00a3a761d8628",
    "name": "Demo Documentation Group",
    "systemId": "GVG7358",
    "description": "Test Import",
    "redemptionChannels": [],
    "status": "voucher-not-created",
    "type": "physical-gv",
    "categoryId": "69044caea5e00a3a761d8608",
    "validity": {
      "type": "limited-time",
      "effectiveFrom": {
        "type": "sales-date",
        "date": "2025-01-03T10:53:26.035Z"
      },
      "expiry": {
        "type": "calendar-date",
        "date": "2025-01-03T10:52:31.000Z",
        "days": null
      },
      "expiryDate": "2025-01-03T10:52:31.000Z"
    },
    "createPack": true,
    "transactionFormatId": "6777ad3f42b0b29b9a92c796",
    "isActive": true,
    "stopSales": false
  }
}

Activation Status

POST /groups/:id/activation-status
Permission: gift-voucher-group -> update

Logic:

  • checks if group exist and updates it's activation status.
curl --location 'https://api.dev-engage.ginesys.one/gv/v1/groups/6904571ea5e00a3a761d8628/activation-status' \
--header 'x-tenant-id: <tenantId>' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token>' \
--data '{
    "isActive": false
}'

Body:

{
  "isActive": false
}

Response:

{
  "status": 200,
  "success": true,
  "data": {
    "msg": "Group Deactivated / Activated Successfully"
  }
}

List Groups

GET /groups/list
Permission: gift-voucher-group -> list
Includes: category,denomination,previewUrl
Supports:Search, Sort, AdvanceFilters, storeId, refCode, gvNo
curl --location 'https://api.dev-engage.ginesys.one/gv/v1/groups/list?include=category%2Cdenominations%2CpreviewUrl&perPage=2&page=1' \
--header 'x-tenant-id: <id>' \
--header 'Authorization: Bearer <token>'

Response:

{
  "status": 200,
  "success": true,
  "data": [
    {
      "id": "6904571ea5e00a3a761d8628",
      "name": "Demo Documentation Group",
      "systemId": "GVG7358",
      "description": "Test Import",
      "redemptionChannels": [],
      "status": "voucher-not-created",
      "type": "physical-gv",
      "categoryId": "69044caea5e00a3a761d8608",
      "validity": {
        "type": "limited-time",
        "effectiveFrom": {
          "type": "sales-date",
          "date": "2025-01-03T10:53:26.035Z"
        },
        "expiry": {
          "type": "calendar-date",
          "date": "2025-01-03T10:52:31.000Z",
          "days": null
        },
        "expiryDate": "2025-01-03T10:52:31.000Z"
      },
      "createPack": true,
      "transactionFormatId": "6777ad3f42b0b29b9a92c796",
      "isActive": false,
      "stopSales": false,
      "category": {
        "id": "69044caea5e00a3a761d8608",
        "name": "jinendra"
      },
      "denominations": [
        {
          "id": "69045a99a5e00a3a761d865e",
          "name": "D1",
          "type": "fix-value",
          "giftValue": 10,
          "saleValue": 20
        }
      ]
    },
    {
      "id": "68d3b4163d04ea37346aeeea",
      "name": "Testtttt",
      "systemId": "GVG7357",
      "description": "erew",
      "redemptionChannels": [
        {
          "appId": "665d43f48b49af2a7c5048aa",
          "clusterIds": ["679dc39e4d5bc083264ef9eb", "67b8753be73dc050bbeeda77"]
        }
      ],
      "status": "voucher-not-created",
      "type": "physical-gv",
      "categoryId": "679dc3f8388e951ccfcb8e23",
      "validity": {
        "type": "limited-time",
        "effectiveFrom": {
          "type": "sales-date",
          "date": null
        },
        "expiry": {
          "type": "period",
          "date": null,
          "days": 42
        }
      },
      "createPack": true,
      "imageSlug": "665d43f38b49af2a7c504865/customer-import/gv/download.png",
      "transactionFormatId": "68d3b2a216aee1acaadd2c33",
      "isActive": true,
      "stopSales": false,
      "category": {
        "id": "679dc3f8388e951ccfcb8e23",
        "name": "dummy_test"
      },
      "denominations": [
        {
          "id": "68d3b4163d04ea37346aeeeb",
          "name": "Ttt",
          "type": "fix-value",
          "giftValue": 555,
          "saleValue": 55
        }
      ],
      "previewUrl": "https://g1crmstagebackendstorage.blob.core.windows.net/customers/665d43f38b49af2a7c504865/customer-import/gv/download.png?sv=2023-11-03&spr=https%2Chttp&st=2025-10-31T06%3A36%3A33Z&se=2025-10-31T07%3A06%3A33Z&sr=b&sp=r&sig=qmcq96N48KQKk%2FPi0Z60q1cxDVPmGB3UcZTEUYg%2B9Cc%3D"
    }
  ],
  "meta": {
    "pagination": {
      "perPage": 2,
      "currentPage": 1,
      "total": 454,
      "totalPages": 227
    }
  }
}

Redemption Channel Details

GET /groups/:id
Permission: gift-voucher-group -> get
Include:denominations,category,config,denominationWiseCount

Logic: if want to include the denominationWiseCount we need to provide the store id. otherwise it's optional.

curl --location 'https://api.dev-engage.ginesys.one/gv/v1/groups/6904571ea5e00a3a761d8628?include=denominations%2Ccategory%2Cconfig' \
--header 'x-tenant-id: <id>' \
--header 'Authorization: Bearer <token>'

Response:

{
  "status": 200,
  "success": true,
  "data": {
    "id": "6904571ea5e00a3a761d8628",
    "name": "Demo Documentation Group",
    "systemId": "GVG7358",
    "description": "Test Import",
    "redemptionChannels": [
      {
        "appId": "665d43f48b49af2a7c5048aa",
        "clusterIds": ["679dc39e4d5bc083264ef9eb"]
      }
    ],
    "status": "voucher-not-created",
    "type": "physical-gv",
    "categoryId": {
      "_id": "69044caea5e00a3a761d8608",
      "createdBy": "665d43fa8b49af2a7c506ada",
      "createActor": "User",
      "name": "jinendra",
      "createdAt": "2025-10-31T05:44:14.773Z",
      "updatedAt": "2025-10-31T05:44:14.773Z",
      "__v": 0
    },
    "validity": {
      "type": "limited-time",
      "effectiveFrom": {
        "type": "sales-date",
        "date": "2025-10-31T10:53:26.035Z"
      },
      "expiry": {
        "type": "calendar-date",
        "date": "2025-12-03T10:52:31.000Z",
        "days": null
      },
      "expiryDate": "2025-12-03T10:52:31.000Z"
    },
    "createPack": true,
    "transactionFormatId": "6777ad3f42b0b29b9a92c796",
    "isActive": false,
    "stopSales": false,
    "denominations": [
      {
        "id": "69045a99a5e00a3a761d865e",
        "name": "D1",
        "type": "fix-value",
        "giftValue": 10,
        "saleValue": 20,
        "voucherCount": 0
      }
    ],
    "category": {
      "id": "69044caea5e00a3a761d8608",
      "name": "jinendra"
    },
    "config": {
      "id": "69045338a5e00a3a761d8614",
      "name": "Demo Config",
      "description": "Something meaningful description of this GV Group",
      "allowPartialRedemption": false,
      "allowMultipleGVInSingleInvoice": false,
      "allowReturn": true,
      "authenticationType": "pin",
      "gvAllowedInSingleInvoice": 10
    }
  }
}

Redemption Channel Details

GET /groups/:id/redemption-channel
Permission: gift-voucher-group -> list

Logic: Returns redemption clusters/channels for group

curl --location 'https://api.dev-engage.ginesys.one/gv/v1/groups/6904571ea5e00a3a761d8628/redemption-channel?include=audits%2Cdenominations' \
--header 'x-tenant-id: <id>' \
--header 'Authorization: Bearer <token>'
{
  "status": 200,
  "success": true,
  "data": [
    {
      "app": {
        "id": "665d43f48b49af2a7c5048aa",
        "name": "Zwing POS"
      },
      "storeClusters": [
        {
          "id": "679dc39e4d5bc083264ef9eb",
          "name": "Hhhhhhhhhhh",
          "description": "tes",
          "systemId": "CL00176"
        }
      ]
    }
  ]
}

Allocate GV To Store

POST /groups/:id/allocate
Permission: gift-voucher-group::update
Body: AllocateGVToStoreDto

Logic: Allocates vouchers to stores/apps

curl --location 'https://api.dev-engage.ginesys.one/gv/v1/groups/6904571ea5e00a3a761d8628/allocate' \
--header 'x-tenant-id: <id>' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token>' \
--data '{
    "mode": "manual-allocation",
    "allocation": [
    {
        "appId": "665d43f48b49af2a7c5048aa",
        "storeId": "679dc3594d5bc083264ef9d3",
        "fromSequence": 1,
        "toSequence": 10,
        "denominationId": "69045a99a5e00a3a761d865e"
    }
]
}'

Body:

Manual Allocation:

{
  "mode": "manual-allocation",
  "allocation": [
    {
      "appId": "665d43f48b49af2a7c5048aa",
      "storeId": "679dc3594d5bc083264ef9d3",
      "fromSequence": 1,
      "toSequence": 10,
      "denominationId": "69045a99a5e00a3a761d865e"
    }
  ]
}

Auto Allocation:

{
  "allocation": [
    {
      "appId": "665d43f48b49af2a7c5048aa",
      "storeId": "679dc3594d5bc083264ef9d3",
      "count": 10,
      "denominationId": "69045a99a5e00a3a761d865e"
    }
  ],
  "mode": "auto-allocation"
}

Response:

{
  "status": 200,
  "success": true,
  "data": {
    "msg": "GVs Allocated to Store Successfully"
  }
}

Get Available Sequences

GET /groups/:id/available-sequences
Permission: gift-voucher-group::get
  • Logic: Computes available sequence ranges
  • DB: group, vouchers
  • Cache: none
curl --location 'https://api.dev-engage.ginesys.one/gv/v1/groups/6904571ea5e00a3a761d8628/available-sequences' \
--header 'x-tenant-id: <id>' \
--header 'Authorization: Bearer <token>'

Response:

{
  "status": 200,
  "success": true,
  "data": [
    {
      "id": "69045a99a5e00a3a761d865e",
      "name": "D1",
      "type": "fix-value",
      "giftValue": 10,
      "saleValue": 20,
      "availableSequences": [
        {
          "start": 1,
          "end": 100,
          "count": 100
        }
      ]
    }
  ]
}

EGV Sales Channel Upsert

POST /groups/egv/sales-channel
Permission: gift-voucher -> create
Body: CreateEGVSaleChannelDto

Logic:

  • This will create a sales channel means that it provide the store authority to create and sell the adhoc egv.
  • Here we can provide the count of vouchers to be sold in reset duration means a store can only generate and sell the voucher provided in a voucher count in side single refresh window.
  • if 100 voucherCount provided and reset duration is of 1 week. A store can only generate 100 voucher in 1 week. This limit refreshes every week.
  • This limits are caches in redis.
  • Creates/updates EGV group sales channel, limits and reset windows
  • Cache: clears CacheKey.EGVStoreLimit
curl --location 'https://api.dev-engage.ginesys.one/gv/v1/groups/egv/sales-channel' \
--header 'x-tenant-id: <id>' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token>' \
--data '
{
    "groupId": "6904726f8487a84bc0e17be5",
    "transactionFormatId": "67a9ada8581a7a0177e86f0d",
    "channels": [
        {
            "appId": "665d43f48b49af2a7c5048aa",
            "storeId": "679dc3594d5bc083264ef9d3",
            "voucherCount": 100,
            "resetDuration": {
                "duration": 1,
                "type": "day"
            },
            "denominationIds": [
                "690475098487a84bc0e17c44"
            ]
        }
    ]
}'

Body

{
  "groupId": "6904726f8487a84bc0e17be5",
  "transactionFormatId": "67a9ada8581a7a0177e86f0d",
  "channels": [
    {
      "appId": "665d43f48b49af2a7c5048aa",
      "storeId": "679dc3594d5bc083264ef9d3",
      "voucherCount": 100,
      "resetDuration": {
        "duration": 1,
        "type": "day" / "week" / "month" / "year"
      },
      "denominationIds": ["690475098487a84bc0e17c44"]
    }
  ]
}

Response:

{
  "groupId": "6904726f8487a84bc0e17be5",
  "transactionFormatId": "67a9ada8581a7a0177e86f0d",
  "channels": [
    {
      "appId": "665d43f48b49af2a7c5048aa",
      "storeId": "679dc3594d5bc083264ef9d3",
      "voucherCount": 100,
      "resetDuration": {
        "duration": 1,
        "type": "day"
      },
      "denominationIds": ["690475098487a84bc0e17c44"]
    }
  ]
}

EGV Sales Channel List

GET /groups/egv/sales-channel
Permission: gift-voucher-group -> list
Include: store, audits
Supports: filters,sorting
Custom: groupId

Logic:

  • It has custom groupId filter.
  • Paginated list of Enabled sales channels and their limits.
curl --location 'https://api.dev-engage.ginesys.one/gv/v1/groups/egv/sales-channel?include=audits%2Cstore&groupId=6904726f8487a84bc0e17be5' \
--header 'x-tenant-id: <id>' \
--header 'Authorization: Bearer <token>'
{
  "status": 200,
  "success": true,
  "data": [
    {
      "id": "690479628f1beb0fcc4c2048",
      "appId": "667411d50d9855b7d19e8f21",
      "groupId": "6904726f8487a84bc0e17be5",
      "storeId": null,
      "denominationIds": [],
      "voucherSaleLimit": 0,
      "reSetDuration": {
        "duration": 0,
        "type": "day"
      },
      "audits": {
        "createdAt": "2025-10-31T08:54:58.094Z",
        "updatedAt": "2025-10-31T09:01:09.415Z",
        "createdById": "665d43fa8b49af2a7c506ada",
        "createActor": "665d43fa8b49af2a7c506ada"
      }
    },
    {
      "id": "690479628f1beb0fcc4c204d",
      "appId": "665d43f48b49af2a7c5048aa",
      "groupId": "6904726f8487a84bc0e17be5",
      "storeId": "679dc3594d5bc083264ef9d3",
      "denominationIds": ["690475098487a84bc0e17c44"],
      "voucherSaleLimit": 100,
      "reSetDuration": {
        "duration": 1,
        "type": "week"
      },
      "audits": {
        "createdAt": "2025-10-31T08:54:58.094Z",
        "updatedAt": "2025-10-31T09:01:09.415Z",
        "createdById": "665d43fa8b49af2a7c506ada",
        "createActor": "665d43fa8b49af2a7c506ada"
      },
      "store": {
        "id": "679dc3594d5bc083264ef9d3",
        "name": "Store 102",
        "refId": "655",
        "address": "baner",
        "state": "Maharashtra",
        "city": "Pune",
        "systemId": "ST02849"
      }
    }
  ],
  "meta": {
    "pagination": {
      "perPage": 15,
      "currentPage": 1,
      "total": 2,
      "totalPages": 1
    }
  }
}

Gift Vouchers APIs (gift-vouchers)

Routes guarded by PermissionGuard and GvRefIdGuard.

Create Physical GVs (async generation)

POST /gift-vouchers/physical-gvs
Permission: gift-voucher -> create

Logic: GV Generation are done using kafka. While generation is in progress no other GV generation request for the same group is taken. we can get the gv generation progress via progress api. Enqueues generation; async progress available

curl --location 'https://api.dev-engage.ginesys.one/gv/v1/gift-vouchers/physical-gvs' \
--header 'x-tenant-id: <id>' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token>' \
--data '{
    "denominationMix": [
        {
            "denominationId": "69045a99a5e00a3a761d865e",
            "quantity": 100
        }
    ],
    "groupId": "6904571ea5e00a3a761d8628",
    "voucherQuantity": 100,
    "transactionFormatId": "690461d30886f3fa617abcd6"
}'

Body:

Group Without Pack

{
  "denominationMix": [
    {
      "denominationId": "69045a99a5e00a3a761d865e",
      "quantity": 100
    }
  ],
  "groupId": "6904571ea5e00a3a761d8628",
  "voucherQuantity": 100,
  "transactionFormatId": "690461d30886f3fa617abcd6"
}

Group With Pack

{
    "denominationMix": [
        {
            "denominationId": "690475c28487a84bc0e17c5e",
            "quantity": 10
        }
    ],
    "groupId": "690475c28487a84bc0e17c5d",
    "voucherQuantity": 10,
    "transactionFormatId": "67a9ad8b581a7a0177e86f03",
    "packs": 10
}

Response:

{
  "status": 200,
  "success": true,
  "data": {
    "msg": "Request Accepted. You will receive a notification once the process is completed"
  }
}

Update GV Status

POST /gift-vouchers/:id/status
Permission: gift-voucher::update
  • Logic: Updates status (block/unblock/return etc.)
curl --location 'https://api.dev-engage.ginesys.one/gv/v1/gift-vouchers/69046455d8f1b31ccfb61767/status' \
--header 'x-tenant-id: <id>' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token>' \
--data '{
    "isBlocked": false
}'

Body

{
    "isBlocked": false / true
}

Response

{
  "status": 200,
  "success": true,
  "data": {
    "msg": "GV Status Updated."
  }
}

List Vouchers

GET /gift-vouchers/list
Permission: gift-voucher::list
Includes:blockedAmount,audits,store,app,pack
Supports: search, sort, advanceFilters,
Filters: storeId,packId,groupId,

Logic:

  • This api has custom filter which can are applied in "and" condition.
  • you can filter the gv list directly by storeId, packId and groupId
  • In the include there is a term "blockedAmount". it's used when you need the blockedAmount of any voucher for information during transactions.
  • Paginated search with includes
curl --location 'https://api.dev-engage.ginesys.one/gv/v1/gift-vouchers/list?groupId=6904571ea5e00a3a761d8628&perPage=1&page=1' \
--header 'x-tenant-id: <id>' \
--header 'Authorization: Bearer <token>'

Response:

{
  "status": 200,
  "success": true,
  "data": [
    {
      "id": "69046456d8f1b31ccfb6188d",
      "sequence": 100,
      "gvNo": "DCA250099CS2KSF",
      "type": "physical-gv",
      "groupId": "6904571ea5e00a3a761d8628",
      "denomination": {
        "name": "D1",
        "type": "fix-value",
        "giftValue": 10,
        "saleValue": 20,
        "_id": "69045a99a5e00a3a761d865e"
      },
      "redeemedAmount": 0,
      "balanceAmount": 10,
      "config": {
        "createdBy": "665d43fa8b49af2a7c506ada",
        "updatedBy": "665d43fa8b49af2a7c506ada",
        "createActor": "User",
        "updateActor": "User",
        "name": "Demo Config",
        "description": "Something meaningful description of this GV Group",
        "allowPartialRedemption": false,
        "allowMultipleGVInSingleInvoice": false,
        "allowReturn": true,
        "verificationType": "pin",
        "gvAllowedInSingleInvoice": 10,
        "_id": "69045338a5e00a3a761d8614",
        "createdAt": "2025-10-31T07:15:11.912Z",
        "updatedAt": "2025-10-31T07:15:11.912Z",
        "__v": 0
      },
      "validity": {
        "type": "limited-time",
        "effectiveFrom": {
          "type": "sales-date",
          "date": "2025-10-31T10:53:26.035Z"
        },
        "expiry": {
          "type": "calendar-date",
          "date": "2025-12-03T10:52:31.000Z",
          "days": null
        },
        "expiryDate": "2025-12-03T10:52:31.000Z"
      },
      "transactions": [],
      "redemptionStatus": "not-redeemed",
      "isAllocated": false,
      "isSold": false,
      "isBlocked": false,
      "isVoid": false,
      "isReturned": false
    }
  ],
  "meta": {
    "pagination": {
      "perPage": 1,
      "currentPage": 1,
      "total": 100,
      "totalPages": 100
    }
  }
}

Get Voucher

GET /gift-vouchers/:id?
Permission: gift-voucher -> get
Include:store,app,audits,recipient

Logic:

  • You can get the gv by id or gvNo. Fetch by id or filters, also computes blockedAmount
  • Also include the store, app, audits, recipient on include bases.
curl --location 'https://api.dev-engage.ginesys.one/gv/v1/gift-vouchers/69046456d8f1b31ccfb6188d?include=store%2Capp%2Caudits%2Crecipient' \
--header 'x-tenant-id: <id>' \
--header 'Authorization: Bearer <token>'
curl --location 'https://api.dev-engage.ginesys.one/gv/v1/gift-vouchers/?include=store%2Capp%2Caudits%2Crecipient&gvNo=DCA250099CS2KSF' \
--header 'x-tenant-id: <id>' \
--header 'Authorization: Bearer <token>'
{
  "status": 200,
  "success": true,
  "data": {
    "id": "69046456d8f1b31ccfb6188d",
    "sequence": 100,
    "gvNo": "DCA250099CS2KSF",
    "type": "physical-gv",
    "groupId": "6904571ea5e00a3a761d8628",
    "denomination": {
      "name": "D1",
      "type": "fix-value",
      "giftValue": 10,
      "saleValue": 20,
      "_id": "69045a99a5e00a3a761d865e"
    },
    "redeemedAmount": 0,
    "balanceAmount": 10,
    "blockedAmount": 0,
    "config": {
      "createdBy": "665d43fa8b49af2a7c506ada",
      "updatedBy": "665d43fa8b49af2a7c506ada",
      "createActor": "User",
      "updateActor": "User",
      "name": "Demo Config",
      "description": "Something meaningful description of this GV Group",
      "allowPartialRedemption": false,
      "allowMultipleGVInSingleInvoice": false,
      "allowReturn": true,
      "verificationType": "pin",
      "gvAllowedInSingleInvoice": 10,
      "_id": "69045338a5e00a3a761d8614",
      "createdAt": "2025-10-31T07:15:11.912Z",
      "updatedAt": "2025-10-31T07:15:11.912Z",
      "__v": 0
    },
    "validity": {
      "type": "limited-time",
      "effectiveFrom": {
        "type": "sales-date",
        "date": "2025-10-31T10:53:26.035Z"
      },
      "expiry": {
        "type": "calendar-date",
        "date": "2025-12-03T10:52:31.000Z",
        "days": null
      },
      "expiryDate": "2025-12-03T10:52:31.000Z"
    },
    "transactions": [],
    "redemptionStatus": "not-redeemed",
    "isAllocated": false,
    "isSold": false,
    "isBlocked": false,
    "isVoid": false,
    "isReturned": false,
    "audits": {
      "createdAt": "2025-10-31T07:25:11.566Z",
      "updatedAt": "2025-10-31T07:25:11.566Z",
      "createdById": "665d43fa8b49af2a7c506ada",
      "createActor": "665d43fa8b49af2a7c506ada"
    }
  }
}

Return GV

POST /gift-vouchers/return
Permission: gift-voucher::update
Body: ReturnGVDto
  • Logic: Processes returns and updates balances/status
  • DB: giftVoucherRepo.returnGV(...)
  • Cache: none

Import Flows

  • Sample CSV
GET /gift-vouchers/imports/sample-csv
Permission: gift-voucher::list
  • Upload URLs
POST /gift-vouchers/imports/upload-urls
Permission: gift-voucher::get
Body: GetSignedUrls
  • Start Import
POST /gift-vouchers/imports
Permission: gift-voucher::create
Body: BulkImportVoucherDto | MigrationBulkImportVoucherDto
  • Job Progress
GET /gift-vouchers/imports/:id
Permission: gift-voucher::get
  • Import Issues
GET /gift-vouchers/imports/:id/issues
Permission: customer::import
Query: GetImportJobIssues
  • Logic: Standard import pipeline; issues paginated
  • DB: import job, failed rows
  • Cache: none

Voucher Generation Progress

GET /gift-vouchers/:id/progress
Permission: gift-voucher -> get
curl --location 'https://api.dev-engage.ginesys.one/gv/v1/gift-vouchers/6904571ea5e00a3a761d8628/progress' \
--header 'x-tenant-id: <id>' \
--header 'Authorization: Bearer <token>'

Response:

{
  "status": 200,
  "success": true,
  "data": {
    "progress": 0
  }
}

Validate Sequences for Allocation

POST /gift-vouchers/sequence/validate
Permission: gift-voucher -> get

Logic:

  • this api validates the voucher sequence allocation before it's allocated so no rejections are provided from the allocation api.
  • allocation can be done in a 2 ways manual and auto.
  • In auto allocation crm decides the allocation of the sequence to the stores
  • In manual allocation user can choose the particular sequence from the available sequences.
  • In auto allocation if quantity is 10 and sequence available has 2 parts first like from 1-10 there is 3 vouchers and 11-17 another 7 vouchers then multiple sequence will be provided in the response to match the quantity.
curl --location 'https://api.dev-engage.ginesys.one/gv/v1/gift-vouchers/sequence/validate' \
--header 'x-tenant-id: <id>' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token>' \
--data '{
    "type": "auto-allocation",
    "groupId": "6904571ea5e00a3a761d8628",
    "allocations": [
        {
            "storeId": "679dc3594d5bc083264ef9d3",
            "denominations": [
                {
                    "id": "69045a99a5e00a3a761d865e",
                    "name": "D1",
                    "type": "fix-value",
                    "giftValue": 10,
                    "saleValue": 20,
                    "count": 10,
                    "denominationId": "69045a99a5e00a3a761d865e"
                }
            ]
        }
    ]
}'

Auto Allocation:

{
  "type": "auto-allocation",
  "groupId": "6904571ea5e00a3a761d8628",
  "allocations": [
    {
      "storeId": "679dc3594d5bc083264ef9d3",
      "denominations": [
        {
          "count": 10,
          "denominationId": "69045a99a5e00a3a761d865e"
        }
      ]
    }
  ]
}

Manual Allocation:

{
  "type": "manual-allocation",
  "groupId": "6904571ea5e00a3a761d8628",
  "allocations": [
    {
      "storeId": "679dc3594d5bc083264ef9d3",
      "denominations": [
        {
          "denominationId": "69045a99a5e00a3a761d865e",
          "start": 1,
          "end": 10
        }
      ]
    },
    {
      "storeId": "679dc3594d5bc083264ef9cd",
      "denominations": [
        {
          "start": 13,
          "end": 15,
          "denominationId": "69045a99a5e00a3a761d865e"
        }
      ]
    }
  ]
}

Response:

{
  "status": 200,
  "success": true,
  "data": [
    {
      "storeId": "679dc3594d5bc083264ef9d3",
      "denominations": [
        {
          "denominationId": "69045a99a5e00a3a761d865e",
          "count": 10,
          "start": 1,
          "end": 10
        }
      ]
    }
  ]
}

Auto Multiple Sequence

{
  "status": 200,
  "success": true,
  "data": [
    {
      "storeId": "679dc3594d5bc083264ef9d3",
      "denominations": [
        {
          "denominationId": "69045a99a5e00a3a761d865e",
          "count": 2,
          "start": 11,
          "end": 12
        },
        {
          "denominationId": "69045a99a5e00a3a761d865e",
          "count": 8,
          "start": 21,
          "end": 28
        }
      ]
    }
  ]
}

Restore GVs

POST /gift-vouchers/restore
Permission: gift-voucher::create
Body: RestoreGVDto
  • Logic: Restores expired/returned GVs when permissible; message includes expired counts
  • DB: updates vouchers

GV Pack APIs (gv-pack)

Routes guarded by PermissionGuard and GvRefIdGuard.

List Packs

GET /gv-pack/list
Permission: gift-voucher -> list
Includes:audits,store,app
Supports: Sorting, filters
Custom Filter: groupId

Logic:

  • It has a customer filter groupId to filter the list for specific group
  • Paginated list of packs
curl --location 'https://api.dev-engage.ginesys.one/gv/v1/gv-pack/list?groupId=690475c28487a84bc0e17c5d&include=audits%2Cstore%2Capp' \
--header 'x-tenant-id: <id>' \
--header 'Authorization: Bearer <token>'

Response

{
  "status": 200,
  "success": true,
  "data": [
    {
      "id": "690475f3d8f1b31ccfb618f8",
      "systemId": "GVP123404",
      "groupId": "690475c28487a84bc0e17c5d",
      "sequence": 123404,
      "status": "created",
      "audits": {
        "createdAt": "2025-10-31T08:40:19.898Z",
        "updatedAt": "2025-10-31T08:40:19.898Z",
        "createdById": "665d43fa8b49af2a7c506ada",
        "createActor": "Akshay P"
      }
    }
  ],
  "meta": {
    "pagination": {
      "perPage": 1,
      "currentPage": 1,
      "total": 10,
      "totalPages": 10
    }
  }
}

Validate Pack Sequences

POST /gv-pack/sequence/validate
Permission: gift-voucher::get
Body: PackSequenceAllocationDto

Logic:

  • There are two types of sequence allocation auto and manual
  • In auto allocation crm decides the sequence.
  • In manual allocation user decides the sequence.
curl --location 'https://api.dev-engage.ginesys.one/gv/v1/gv-pack/sequence/validate' \
--header 'x-tenant-id: <id>' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token>' \
--data '{
    "type": "auto-allocation",
    "groupId": "690475c28487a84bc0e17c5d",
    "allocations": [
        {
            "storeId": "679dc3594d5bc083264ef9d3",
            "count": 10
        }
    ]
}'

Body:

Auto Allocation

{
    "type": "auto-allocation",
    "groupId": "690475c28487a84bc0e17c5d",
    "allocations": [
        {
            "storeId": "679dc3594d5bc083264ef9d3",
            "count": 10
        }
    ]
}

Manual Allocation

{
    "type": "manual-allocation",
    "groupId": "690475c28487a84bc0e17c5d",
    "allocations": [
        {
            "storeId": "679dc3594d5bc083264ef9d3",
            "start": 123395,
            "end": 123396
        }
    ]
}

Sale & Redemption APIs (gift-voucher/sale)

Routes guarded by PermissionGuard and GvRefIdGuard.

Add Physical GV to Cart

POST /gift-voucher/sale/physical-gvs/cart
Permission: gift-voucher::sale

Operations: Add GV to Cart (New / Existing) Modes: Auto, Manual

Logic:

  • This api can add gv to cart for selling.
  • Cart will be created once the gv are added a unique cart id will be provided (sessionId)
  • voucher can be added automatic or manual.
  • In auto mode voucher gift value and denomination needs to be provided.
  • In manual mode gvId or gvNo needs to be provided.
  • Cart is stored inside the redis cache
  • While adding voucher to cart if cart session id is provided it will not create a new cart and will add the voucher to the provided cart.
  • Validates group, voucher status/allocation, locks vouchers, builds cart item(s)
  • DB: reads groups, vouchers, packs
  • Cache:
    • Cart JSON at CacheKey.GVCart(<sessionId>) (EX 900)
    • Per-GV cart presence at CacheKey.GVInCart(<gvId>) (EX 900)
    • Redis Lua to merge/update cart preserving TTL
curl --location 'https://api.dev-engage.ginesys.one/gv/v1/gift-voucher/sale/physical-gvs/cart' \
--header 'x-tenant-id: <id>' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token>' \
--data '{
    "mode": "auto",
    "vouchers": [
        {
            "voucherCount": 1,
            "groupId": "6904571ea5e00a3a761d8628",
            "denominationType": "fix-value",
            "giftValue": 10
        }
    ],
    "storeId": "679dc3594d5bc083264ef9d3"
}'
Auto Add

{
    "mode": "auto",
    "vouchers": [
        {
            "voucherCount": 1,
            "groupId": "6904571ea5e00a3a761d8628",
            "denominationType": "fix-value",
            "giftValue": 10
        }
    ],
    "storeId": "679dc3594d5bc083264ef9d3"
}

Manual Add

{
    "sessionId": "e7dee84d-bccf-48f1-8199-32e74666ee5d", (optional if new cart)
    "mode": "manual",
    "vouchers": [
        {
            "gvId": "69046454d8f1b31ccfb61764",
            "groupId": "6904571ea5e00a3a761d8628"
        }
    ],
    "storeId": "679dc3594d5bc083264ef9d3"
}

Response:

{
  "status": 200,
  "success": true,
  "data": {
    "sessionId": "76dda5a6-c3a7-448e-957c-5ca5165a08e7",
    "physicalGVs": [
      {
        "saleValue": 20,
        "giftValue": 10,
        "gvId": "69046454d8f1b31ccfb61764",
        "groupId": "6904571ea5e00a3a761d8628",
        "appId": "665d43f48b49af2a7c5048aa",
        "storeId": "679dc3594d5bc083264ef9d3",
        "gvNo": "DCA250000NNJXSF",
        "sequence": 1,
        "type": "physical-gv",
        "denominationType": "fix-value",
        "denomination": {
          "name": "D1",
          "type": "fix-value",
          "giftValue": 10,
          "saleValue": 20,
          "_id": "69045a99a5e00a3a761d865e"
        },
        "verificationType": "pin",
        "groupName": "Demo Documentation Group",
        "groupDescription": "Test Import"
      }
    ]
  }
}

Confirm GV Sale

POST /gift-voucher/sale/confirm-sale
Permission: gift-voucher::sale
Body: ConfirmGVSaleDto
  • Logic: Requires customer tagged in cart; marks vouchers sold, generates PIN for Pin-config, sends notifications, attaches invoice (task)
  • Cache: deletes cart key after success
  • Notifications: email/SMS via CommonLib; fallback Kafka dispatch
curl --location 'https://api.dev-engage.ginesys.one/gv/v1/gift-voucher/sale/confirm-sale' \
--header 'x-tenant-id: <id>' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token>' \
--data '{
    "sessionId": "e7dee84d-bccf-48f1-8199-32e74666ee5d",
    "invoiceId": "e7dee84d-bccf-48f1-8199-32e74666ee5d"
}'

Body:

{
  "sessionId": "e7dee84d-bccf-48f1-8199-32e74666ee5d",
  "invoiceId": "e7dee84d-bccf-48f1-8199-32e74666ee5d"
}

Response:

{
  "status": 200,
  "success": true,
  "data": {
    "msg": "Items in cart marked as sold."
  }
}

Add EGV to Cart (on-demand creation)

POST /gift-voucher/sale/e-gvs/cart
Permission: gift-voucher::sale
Body: AddEGVToCartDto

Logic:

  • Validates group/channel, checks sale limits, creates EGVs, adds to cart
  • While adding the gv in the cart it will create a egv as egv's are adhoc created.
  • If GV is not sold it's sequence will be wasted.

DB: inserts vouchers; sequences and transaction numbers via commonLibService

Cache: cart at CacheKey.GVCart(<sessionId>); store limits at CacheKey.EGVStoreLimit(groupId, storeId|appId) with periodic reset

curl --location 'https://api.dev-engage.ginesys.one/gv/v1/gift-voucher/sale/e-gvs/cart' \
--header 'x-tenant-id: <id>' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token>' \
--data '{

    "eGVs": [
        {
            "voucherCount": 1,
            "groupId": "6904726f8487a84bc0e17be5",
            "giftValue":100,

            "denominationType": "dynamic-value"
        }
    ],
    "storeId": "679dc3594d5bc083264ef9d3"
}'

Body

{
  "eGVs": [
    {
      "voucherCount": 1,
      "groupId": "6904726f8487a84bc0e17be5",
      "giftValue": 100,

      "denominationType": "dynamic-value"
    }
  ],
  "storeId": "679dc3594d5bc083264ef9d3"
}

Response:

{
  "status": 200,
  "success": true,
  "data": {
    "sessionId": "d38f3c2b-c1c0-4245-a425-7049287e1d7a",
    "eGVs": [
      {
        "gvId": "690488b98487a84bc0e17d8d",
        "appId": "665d43f48b49af2a7c5048aa",
        "storeId": "679dc3594d5bc083264ef9d3",
        "type": "egv",
        "groupId": "6904726f8487a84bc0e17be5",
        "denomination": {
          "name": "Doc 2",
          "type": "dynamic-value",
          "saleValuePercentageGiftValue": 100,
          "minGiftValue": 100,
          "maxGiftValue": 1000,
          "_id": "690475098487a84bc0e17c44"
        },
        "giftValue": 100,
        "saleValue": 100,
        "verificationType": "pin",
        "gvNo": "OB0011",
        "sequence": 1,
        "denominationType": "dynamic-value",
        "groupName": "Doc 1",
        "groupDescription": "doc 1"
      }
    ]
  }
}

Redeem GV (direct)

POST /gift-voucher/sale/redeem
Permission: gift-voucher::redeem
Body: RedeemGVDto
  • Logic: Validates expiry/effective date, sold status, redemption channel, verification (OTP/Pin/None), multiple-GV rules, partial policy; records debit transaction and updates status
  • DB: giftVoucherRepo.redeemGV(...)
  • Cache: OTP session OtpCacheKey.Otp(transactionId); Pin verification CacheKey.GVVerification(gvId, transactionId, GVPinVerification)

Block Amount (pre-authorization)

POST /gift-voucher/sale/block
Permission: gift-voucher::redeem
Body: BlockGVAmountDto
  • Logic: Checks already-blocked amount, validates like redeem, creates blocked record (30 mins expiry)
  • DB: gvBlockedAmountRepo.new(...)
  • Cache: OTP/Pin verification as above

Confirm Redemption (for blocked)

POST /gift-voucher/sale/confirm-redeem
Permission: gift-voucher::redeem
Body: ConfirmGVRedemptionDto
  • Logic: Validates all redemptionIds are valid and from single order; groups by GV, aggregates debits, determines final status, sends notifications, updates GV transactions, removes blocks
  • DB: giftVoucherRepo.redeemBulkGV(...), gvBlockedAmountRepo.unBlockGVAmount(...)

Unblock Amount

POST /gift-voucher/sale/unblock-amount
Permission: gift-voucher::redeem
Body: UnblockGVAmountDto
  • Logic: Deletes block docs; errors if already redeemed/unblocked
  • DB: gvBlockedAmountRepo.unBlockGVAmountDelete(...)

Send PIN (Pin verification only)

POST /gift-voucher/sale/verification/initiate
Permission: gift-voucher::redeem
Body: GVSendPinDto
  • Logic: For Pin config, issues a transactionId and caches verification context for 20 minutes; sends PIN via notifications
  • Cache: CacheKey.GVVerification(gvId, transactionId, GVPinVerification)

Verify (Pin)

POST /gift-voucher/sale/verify
Permission: gift-voucher::redeem
Body: GVVerificationDto
  • Logic: Validates provided PIN, sets cache flag verify=true
  • Cache: CacheKey.GVVerification(gvId, transactionId, GVPinVerification)
curl --location 'https://api.dev-engage.ginesys.one/gv/v1/gift-voucher/sale/verify' \
--header 'x-tenant-id: <id>' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token>' \
--data '{
    "transactionId":"c0f44474-0580-4ca2-abd9-29d2d0a66f6b",
    "gvId":"690488b98487a84bc0e17d8d",
    "verificationCode":"1463"
}'

Body

{
  "transactionId": "c0f44474-0580-4ca2-abd9-29d2d0a66f6b",
  "gvId": "690488b98487a84bc0e17d8d",
  "verificationCode": "1463"
}

Response

{
  "status": 200,
  "success": true,
  "data": {
    "isVerified": true,
    "transactionId": "c0f44474-0580-4ca2-abd9-29d2d0a66f6b"
  }
}

Cart Helpers

Get cart

GET /gift-voucher/sale/cart/:sessionId/validity (Permission: gift-voucher::sale)
curl --location 'https://api.dev-engage.ginesys.one/gv/v1/gift-voucher/sale/cart/76dda5a6-c3a7-448e-957c-5ca5165a08e7' \
--header 'x-tenant-id: <id>' \
--header 'Authorization: Bearer <token>'

Response:

{
  "status": 200,
  "success": true,
  "data": {
    "cart": {
      "sessionId": "76dda5a6-c3a7-448e-957c-5ca5165a08e7",
      "physicalGVs": [
        {
          "verificationType": "pin",
          "type": "physical-gv",
          "sequence": 1,
          "appId": "665d43f48b49af2a7c5048aa",
          "denomination": {
            "saleValue": 20,
            "type": "fix-value",
            "name": "D1",
            "_id": "69045a99a5e00a3a761d865e",
            "giftValue": 10
          },
          "groupDescription": "Test Import",
          "saleValue": 20,
          "groupName": "Demo Documentation Group",
          "storeId": "679dc3594d5bc083264ef9d3",
          "gvNo": "DCA250000NNJXSF",
          "denominationType": "fix-value",
          "giftValue": 10,
          "gvId": "69046454d8f1b31ccfb61764",
          "groupId": "6904571ea5e00a3a761d8628"
        }
      ]
    }
  }
}

Delete cart

DELETE /gift-voucher/sale/cart/:sessionId (Permission: gift-voucher::sale)
curl --location --request DELETE 'https://api.dev-engage.ginesys.one/gv/v1/gift-voucher/sale/cart/ae639831-641e-4104-9bee-1f8f2e6ea3dc' \
--header 'x-tenant-id: <id>' \
--header 'Authorization: Bearer <token>'

Response:

No Response only api status will be 204.

Cart validity

GET /gift-voucher/sale/cart/:sessionId/validity
(Permission: gift-voucher::sale)
curl --location 'https://api.dev-engage.ginesys.one/gv/v1/gift-voucher/sale/cart/76dda5a6-c3a7-448e-957c-5ca5165a08e7/validity' \
--header 'x-tenant-id: <id>' \
--header 'Authorization: Bearer '

Response:

{
  "status": 200,
  "success": true,
  "data": {
    "isCartValid": true
  }
}

Remove Item From cart

POST /gift-voucher/sale/cart/remove (Permission: gift-voucher::sale)
curl --location 'https://api.dev-engage.ginesys.one/gv/v1/gift-voucher/sale/cart/remove' \
--header 'x-tenant-id: <id>' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token>' \
--data '{
    "sessionId": "76dda5a6-c3a7-448e-957c-5ca5165a08e7",
    // "groupIds": ["{{gvGroupId}}"]
    // "egvIds": ["6780cbf27564116cacdb1e61"]
    "pgvIds": ["69046454d8f1b31ccfb61764"]
}'

Body

You can remove the egv and pgv via providing the ids or you can remove the gvs of single group. send only key which needs to be remove.

{
    "sessionId": "76dda5a6-c3a7-448e-957c-5ca5165a08e7",
    "groupIds": ["{{gvGroupId}}"]
    "egvIds": ["6780cbf27564116cacdb1e61"]
    "pgvIds": ["69046454d8f1b31ccfb61764"]
}

Response:

{
  "status": 200,
  "success": true,
  "data": {
    "cart": {
      "sessionId": "e7dee84d-bccf-48f1-8199-32e74666ee5d",
      "physicalGVs": {}
    }
  }
}

Tag Customer to cart

POST   /gift-voucher/sale/cart/tag
(Permission: gift-voucher::sale)
curl --location 'https://api.dev-engage.ginesys.one/gv/v1/gift-voucher/sale/cart/tag' \
--header 'x-tenant-id: <id>' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token>' \
--data '{
    "customerId": "66de9e0022f11e899be88f8c",
    "sessionId": "e7dee84d-bccf-48f1-8199-32e74666ee5d"
}'

Body

{
  "customerId": "66de9e0022f11e899be88f8c",
  "sessionId": "e7dee84d-bccf-48f1-8199-32e74666ee5d"
}

Response:

{
  "status": 200,
  "success": true,
  "data": {
    "cart": {
      "physicalGVs": [
        {
          "verificationType": "pin",
          "type": "physical-gv",
          "sequence": 1,
          "groupDescription": "Test Import",
          "denomination": {
            "saleValue": 20,
            "type": "fix-value",
            "name": "D1",
            "_id": "69045a99a5e00a3a761d865e",
            "giftValue": 10
          },
          "groupId": "6904571ea5e00a3a761d8628",
          "saleValue": 20,
          "appId": "665d43f48b49af2a7c5048aa",
          "storeId": "679dc3594d5bc083264ef9d3",
          "gvNo": "DCA250000NNJXSF",
          "denominationType": "fix-value",
          "giftValue": 10,
          "gvId": "69046454d8f1b31ccfb61764",
          "groupName": "Demo Documentation Group"
        }
      ],
      "sessionId": "e7dee84d-bccf-48f1-8199-32e74666ee5d",
      "customerId": "66de9e0022f11e899be88f8c"
    }
  }
}

Attach Recipient to cart

POST   /gift-voucher/sale/attach-recipient
(Permission: gift-voucher::sale)

Logic:

  • Will attach recipient
curl --location 'https://api.dev-engage.ginesys.one/gv/v1/gift-voucher/sale/attach-recipient' \
--header 'x-tenant-id: <id>' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token>' \
--data-raw '{
    "sessionId": "e7dee84d-bccf-48f1-8199-32e74666ee5d",
    "recipients": [
        {
            "gvId": "69046454d8f1b31ccfb61764",
            "email": "jinendra.mehta@indexnine.com",
            "phoneNumber": "+919384928458"
        }
    ]
}'

Body

{
  "sessionId": "{{sessionId}}",
  "recipients": [
    {
      "gvId": "69046454d8f1b31ccfb61764",
      "email": "jinendra.mehta@indexnine.com",
      "phoneNumber": "+919384928458"
    }
  ]
}

Response:

{
  "status": 200,
  "success": true,
  "data": {
    "msg": "Recipient attached successfully"
  }
}

Detach Recipient to cart

POST   /gift-voucher/sale/detach-recipient
(Permission: gift-voucher::sale)

Logic:

  • Will Remove the attached recipient
curl --location 'https://api.dev-engage.ginesys.one/gv/v1/gift-voucher/sale/detach-recipient' \
--header 'x-tenant-id: <token>' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token>' \
--data '{
    "sessionId": "e7dee84d-bccf-48f1-8199-32e74666ee5d",
    "gvIds": ["69046454d8f1b31ccfb61764"]
}'

Body

{
  "sessionId": "{{sessionId}}",
  "gvIds": ["69046454d8f1b31ccfb61764"]
}

Response:

{
  "status": 200,
  "success": true,
  "data": {
    "msg": "Recipient detached successfully"
  }
}

Void Invoice

POST /gift-voucher/sale/invoice/void (Permission: gift-voucher::sale)

Logic:

  • Upon Voiding the invoice voucher associated with these invoice will be marked as a void and will not be allowed to redeem.
curl --location 'https://api.dev-engage.ginesys.one/gv/v1/gift-voucher/sale/invoice/void' \
--header 'x-tenant-id: <id>' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token>' \
--data '{
    "invoiceId": "e7dee84d-bccf-48f1-8199-32e74666ee5d"
}'

Body

{
  "invoiceId": "e7dee84d-bccf-48f1-8199-32e74666ee5d"
}

Response:

{
  "status": 200,
  "success": true,
  "data": {
    "msg": "Invoice void successfully"
  }
}

Redemption

Block GV Amount

POST gift-voucher/sale/block
(Permission: gift-voucher::redeem)

Logic:

  • Upon Blocking the amount this amount will be blocked from the voucher and will not be allowed to use anywhere else. if there is remaining amount on the voucher it can be use at other transaction.
  • This block is only for the 30 minutes. if not confirmed it will be release for general use.
curl --location 'https://api.dev-engage.ginesys.one/gv/v1/gift-voucher/sale/block' \
--header 'x-tenant-id: <id>' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token>' \
--data '
{
    "gvId": "690488b98487a84bc0e17d8d",
    "amount": 100,
    "storeId": "679dc3594d5bc083264ef9d3",
    "orderId": "ODR101",
    "transactionId": "c0f44474-0580-4ca2-abd9-29d2d0a66f6b"
}'

Body

{
  "gvId": "690488b98487a84bc0e17d8d", (optional if provided gvNo)
  "gvNo": "690488b98487a84bc0e17d8d", (Optional if provide gvId)
  "amount": 100,
  "storeId": "679dc3594d5bc083264ef9d3",
  "orderId": "ODR101",
  "transactionId": "c0f44474-0580-4ca2-abd9-29d2d0a66f6b"
}

Response:

{
  "status": 200,
  "success": true,
  "data": {
    "_id": "69048e098487a84bc0e17de1",
    "gvId": "690488b98487a84bc0e17d8d",
    "amount": 100,
    "transaction": {
      "transactionId": "c0f44474-0580-4ca2-abd9-29d2d0a66f6b",
      "type": "debit",
      "debit": 100,
      "balanceAmount": 0,
      "invoiceId": "ODR101",
      "appId": "665d43fa8b49af2a7c506ada",
      "storeId": "679dc3594d5bc083264ef9d3",
      "transactionTime": "2025-10-31T10:23:05.156Z",
      "effectiveFrom": "2025-10-31T08:22:11.502Z",
      "validUpto": "2026-10-31T08:22:11.502Z"
    },
    "orderId": "ODR101",
    "deleteIfNotConfirmedAt": "2025-10-31T10:53:05.156Z"
  }
}

UnBlock GV Amount

POST gift-voucher/sale/unblock-amount
(Permission: gift-voucher::redeem)

Logic:

  • it will revert the block amount.
curl --location 'https://api.dev-engage.ginesys.one/gv/v1/gift-voucher/sale/unblock-amount' \
--header 'x-tenant-id: <id>' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token>' \
--data '{
    "redemptionIds": ["69048e098487a84bc0e17de1"]}'

Body

{
  "redemptionIds": ["69048e098487a84bc0e17de1"] (this is the _id provide on block api response)
}

Response:

{
  "status": 200,
  "success": true,
  "data": {
    "msg": "Amount unblocked successfully"
  }
}

Confirm GV Redemption

POST gift-voucher/sale/confirm-redeem
(Permission: gift-voucher::redeem)

Logic:

  • it will confirm the redemption.
curl --location 'https://api.dev-engage.ginesys.one/gv/v1/gift-voucher/sale/confirm-redeem' \
--header 'x-tenant-id: <id>' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token>' \
--data '{
    "redemptionIds": ["69048ebd8487a84bc0e17e0d"],
    "invoiceId": "c0f44474-0580-4ca2-abd9"
}'

Body

{
  "redemptionIds": ["69048e098487a84bc0e17de1"], (redemptionIds are _id provide on block api response)
  "invoiceId": "c0f44474-0580-4ca2-abd9"
}

Response

{
  "status": 200,
  "success": true,
  "data": {
    "msg": "Redemption confirmed successfully"
  }
}

Restore GV

POST gift-voucher/restore
(Permission: gift-voucher::redeem)

Logic:

  • It will restore all the amount redeemed on the provided invoiceId of the gv. it will add the revert transaction and will credit the amounts in the respective gvs.
curl --location 'https://api.dev-engage.ginesys.one/gv/v1/gift-vouchers/restore' \
--header 'x-tenant-id: <id>' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token>' \
--data '{
    "storeId": "679dc3594d5bc083264ef9d3",
    "invoiceId": "c0f44474-0580-4ca2-abd9"
}'

Body

{
  "storeId": "679dc3594d5bc083264ef9d3",
  "invoiceId": "c0f44474-0580-4ca2-abd9"
}

Response

{
  "status": 200,
  "success": true,
  "data": {
    "msg": "Vouchers have been restored."
  }
}

Return GV

POST gift-voucher/return
(Permission: gift-voucher::redeem)

Logic:

  • It will be use if in case of gv is in not-redeemed state and being return to the store to get the cash amount back.
  • upon return gv will not be able to redeem.
curl --location 'https://api.dev-engage.ginesys.one/gv/v1/gift-vouchers/return' \
--header 'x-tenant-id: <id>' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token>' \
--data '{
    "returnGV":[
        {
            "refCode":"OB0011",
            "reason":"not required",
            "invoiceId":"c0f44474-0580-4ca2-abd9return"
        }
    ]
}'

Body

{
  "returnGV": [
    {
      "refCode": "OB0011",
      "reason": "not required",
      "invoiceId": "c0f44474-0580-4ca2-abd9return"
    }
  ]
}

Response

{
  "status": 200,
  "success": true,
  "data": [
    {
      "id": "690488b98487a84bc0e17d8d",
      "sequence": 1,
      "gvNo": "OB0011",
      "type": "egv",
      "groupId": "6904726f8487a84bc0e17be5",
      "appId": "665d43f48b49af2a7c5048aa",
      "denomination": {
        "name": "Doc 2",
        "type": "dynamic-value",
        "saleValuePercentageGiftValue": 100,
        "minGiftValue": 100,
        "maxGiftValue": 1000,
        "_id": "690475098487a84bc0e17c44"
      },
      "redeemedAmount": 0,
      "balanceAmount": 0,
      "config": {
        "createdBy": "665d43fa8b49af2a7c506ada",
        "updatedBy": "665d43fa8b49af2a7c506ada",
        "createActor": "User",
        "updateActor": "User",
        "name": "Demo Config",
        "description": "Something meaningful description of this GV Group",
        "allowPartialRedemption": false,
        "allowMultipleGVInSingleInvoice": false,
        "allowReturn": true,
        "verificationType": "pin",
        "gvAllowedInSingleInvoice": 10,
        "_id": "69045338a5e00a3a761d8614",
        "createdAt": "2025-10-31T08:36:25.993Z",
        "updatedAt": "2025-10-31T08:36:25.993Z",
        "__v": 0
      },
      "validity": {
        "type": "limited-time",
        "effectiveFrom": {
          "type": "calendar-date",
          "date": "2025-10-31T08:22:11.502Z"
        },
        "expiry": {
          "type": "period",
          "date": "2025-11-29T18:30:00.000Z",
          "days": 365
        },
        "expiryDate": "2026-10-31T08:22:11.502Z"
      },
      "transactions": [
        {
          "type": "credit",
          "credit": 100,
          "balanceAmount": 100,
          "appId": "665d43f48b49af2a7c5048aa",
          "storeId": "679dc3594d5bc083264ef9d3",
          "transactionTime": "2025-10-31T10:06:05.305Z",
          "effectiveFrom": "2025-10-31T08:22:11.502Z"
        },
        {
          "transactionId": "c0f44474-0580-4ca2-abd9",
          "type": "debit",
          "debit": 100,
          "balanceAmount": 0,
          "invoiceId": "c0f44474-0580-4ca2-abd9",
          "appId": "665d43fa8b49af2a7c506ada",
          "storeId": "679dc3594d5bc083264ef9d3",
          "transactionTime": "2025-10-31T10:26:05.315Z",
          "effectiveFrom": "2025-10-31T08:22:11.502Z",
          "validUpto": "2026-10-31T08:22:11.502Z"
        },
        {
          "transactionId": null,
          "invoiceId": "c0f44474-0580-4ca2-abd9",
          "type": "credit",
          "balanceAmount": 100,
          "credit": 100,
          "storeId": "679dc3594d5bc083264ef9d3",
          "appId": "665d43fa8b49af2a7c506ada"
        },
        {
          "type": "return",
          "balanceAmount": 0,
          "invoiceId": "c0f44474-0580-4ca2-abd9return",
          "comment": "not required"
        }
      ],
      "redemptionStatus": "not-redeemed",
      "isAllocated": true,
      "isSold": true,
      "isBlocked": false,
      "isVoid": false,
      "isReturned": true,
      "invoiceId": "d38f3c2b-c1c0-4245-a425-7049287e1d7a",
      "saleDate": "2025-10-31T10:06:05.305Z"
    }
  ]
}

Health

GET /health
Auth: SkipAuth

Edit on GitHub