Yoyo Logo

Redemption

Redeem loyalty vouchers and gift cards at POS or online

Understanding the Dual-Message Flow

All redemptions use a two-step process to ensure reliable transaction handling:

Customer
POS
Yoyo Platform
wiCode API
1Customer presents wiCode
2Transaction Request
3Transaction Response
4Advice Request
5Advice Response
6Customer receives response
Request Response
1Transaction Request

Sends the wiCode and basket amount. Returns authorization and amount processed.

2Advise Request

Confirms final state (FINALISE or REVERSE). Must always be sent.

In-Store Point of Sale

Integrate with your POS system for in-store redemptions

Integration Flow

  1. 1Customer presents wiCode at checkout (scanned or entered manually)
  2. 2POS captures wiCode and sends Transaction Request to Yoyo with basket amount
  3. 3Yoyo authorises and returns the discount amount to apply
  4. 4POS applies discount to basket and completes the sale
  5. 5POS sends Advise Request to finalize (FINALISE or REVERSE)
# Step 1: Send the Transaction Request. IMPORTANT: set storeTrxDetails.basketId to YOUR own reference for this order — it must be unique per transaction. It is how this redemption is reconciled, settled, and traced back to a wiCode across both systems.
curl -X POST "https://rad2.wigroup.co:8181/wigroup-transactionengine/pos-providers/transaction" \
  -H "id: {posId}" \
  -H "password: {posPassword}" \
  -H "apiClientVersion: {apiClientVersion}" \
  -H "apiServerVersion: 1.14" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "PAYMENT",
    "totalAmount": 10000,
    "basketAmount": 10000,
    "product": [
        {
            "id": "COFFEE345",
            "units": 1,
            "pricePerUnit": 5000
        },
        {
            "id": "TEA346",
            "units": 1,
            "pricePerUnit": 5000
        }
    ],
    "token": {
        "id": "wicode_here",
        "type": "WICODE"
    },
    "storeTrxDetails": {
        "storeId": 1050,
        "basketId": "<insert your unique basket identifier here>",
        "trxId": "1",
        "posId": "online",
        "cashierId": "online"
    }
}'
Critical Field: basketId

The basketId links redemptions to your internal systems for settlement and auditing. Do not treat storeTrxDetails as boilerplate.

  • You Define It: Pass your system's unique internal order reference.
  • Strict Uniqueness: Never reuse a basketId. Unique IDs are required to keep transactions traceable.
  • Powers Reconciliation: Pair your basketId with the returned wiTrxId to audit and reconcile payments across both systems.
Transaction Response
{
  "token": { "id": "1234567", "type": "WICODE" },
  "type": "PAYMENT",
  "storeTrxDetails": {
    "storeId": 1050,
    "retailerId": 999,
    "basketId": "order-000123",
    "trxId": "12345"
  },
  "wiTrxId": 431711,
  "totalAmountProcessed": 10000,
  "basketAmountProcessed": 10000,
  "amountToSettle": 0,
  "billAmount": 10000,
  "vsp": {
    "id": 20016,
    "name": "wiCoupon",
    "trxId": "569023",
    "responseCode": "-1",
    "responseDesc": "Success"
  },
  "discount": [
    { "name": "API Voucher Documentation", "amount": 10000 }
  ],
  "redemptions": [
    {
      "description": "API Voucher Documentation",
      "processedAmount": 10000,
      "type": "VOUCHER",
      "vspId": 20016
    }
  ],
  "responseCode": "-1",
  "responseDesc": "Success"
}
# Step 2: Finalize the transaction (FINALISE or REVERSE)
curl -X POST "https://rad2.wigroup.co:8181/wigroup-transactionengine/pos-providers/advise" \
  -H "id: {posId}" \
  -H "password: {posPassword}" \
  -H "apiClientVersion: {apiClientVersion}" \
  -H "apiServerVersion: 1.14" \
  -H "Content-Type: application/json" \
  -d '{
    "action": "FINALISE",
    "originalTrx": {
        "wiTrxId": 431711,
        "type": "PAYMENT",
        "storeTrxDetails": {
            "retailerId": 999,
            "storeId": 1050,
            "trxId": "12345"
        }
    }
}'
Response Codes
-1 = Success
!Any other code = Failed
Full response code reference
Notes
basketAmount

The value of the items in the basket before any discounts are applied.

totalAmount

The final amount the customer pays after the loyalty discount has been applied. Send basketAmount upfront; use totalAmount when finalising the transaction.

Online Checkout

Accept wiCodes in your eCommerce checkout flow

Integration Flow

  1. 1Customer enters wiCode at checkout → discount instantly applied to basket
  2. 2Customer pays remaining balance with card or other payment method
  3. 3Advise Request sent to finalize (FINALISE on success, REVERSE if cancelled)
# Step 1: Send the Transaction Request. IMPORTANT: set storeTrxDetails.basketId to YOUR own reference for this order — it must be unique per transaction. It is how this redemption is reconciled, settled, and traced back to a wiCode across both systems.
curl -X POST "https://rad2.wigroup.co:8181/wigroup-transactionengine/pos-providers/transaction" \
  -H "id: {posId}" \
  -H "password: {posPassword}" \
  -H "apiClientVersion: {apiClientVersion}" \
  -H "apiServerVersion: 1.14" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "PAYMENT",
    "totalAmount": 10000,
    "basketAmount": 10000,
    "product": [
        {
            "id": "COFFEE345",
            "units": 1,
            "pricePerUnit": 5000
        },
        {
            "id": "TEA346",
            "units": 1,
            "pricePerUnit": 5000
        }
    ],
    "token": {
        "id": "wicode_here",
        "type": "WICODE"
    },
    "storeTrxDetails": {
        "storeId": 1050,
        "basketId": "<insert your unique basket identifier here>",
        "trxId": "1",
        "posId": "online",
        "cashierId": "online"
    }
}'
Critical Field: basketId

The basketId links redemptions to your internal systems for settlement and auditing. Do not treat storeTrxDetails as boilerplate.

  • You Define It: Pass your system's unique internal order reference.
  • Strict Uniqueness: Never reuse a basketId. Unique IDs are required to keep transactions traceable.
  • Powers Reconciliation: Pair your basketId with the returned wiTrxId to audit and reconcile payments across both systems.
Transaction Response
{
  "token": { "id": "1234567", "type": "WICODE" },
  "type": "PAYMENT",
  "storeTrxDetails": {
    "storeId": 1050,
    "retailerId": 999,
    "basketId": "order-000123",
    "trxId": "12345"
  },
  "wiTrxId": 431711,
  "totalAmountProcessed": 10000,
  "basketAmountProcessed": 10000,
  "amountToSettle": 0,
  "billAmount": 10000,
  "vsp": {
    "id": 20016,
    "name": "wiCoupon",
    "trxId": "569023",
    "responseCode": "-1",
    "responseDesc": "Success"
  },
  "discount": [
    { "name": "API Voucher Documentation", "amount": 10000 }
  ],
  "redemptions": [
    {
      "description": "API Voucher Documentation",
      "processedAmount": 10000,
      "type": "VOUCHER",
      "vspId": 20016
    }
  ],
  "responseCode": "-1",
  "responseDesc": "Success"
}
# Step 2: Finalize the transaction (FINALISE or REVERSE)
curl -X POST "https://rad2.wigroup.co:8181/wigroup-transactionengine/pos-providers/advise" \
  -H "id: {posId}" \
  -H "password: {posPassword}" \
  -H "apiClientVersion: {apiClientVersion}" \
  -H "apiServerVersion: 1.14" \
  -H "Content-Type: application/json" \
  -d '{
    "action": "FINALISE",
    "originalTrx": {
        "wiTrxId": 431711,
        "type": "PAYMENT",
        "storeTrxDetails": {
            "retailerId": 999,
            "storeId": 1050,
            "trxId": "12345"
        }
    }
}'
Key Response Fields
  • Returns discount amount to apply
  • Partial redemptions supported
  • Includes transaction ID for advise
Important Notes
  • Always send Advise after Transaction
  • Use REVERSE if order is cancelled
  • Always remove a wiCode and REVERSE it when a customer edits a basket
  • Handle partial redemptions gracefully

Seamless Experience: When the customer enters their wiCode, the Transaction Request returns the discount amount instantly. Apply this to the basket and let the customer pay the remainder with their preferred payment method.

Transaction History

Retrieve a list of transactions for a store, useful for reconciliation and reporting. Filter by date range and basket.

curl -X POST "https://rad2.wigroup.co:8181/wigroup-transactionengine/pos-providers/transaction-history" \
  -H "id: {posId}" \
  -H "password: {posPassword}" \
  -H "apiClientVersion: {apiClientVersion}" \
  -H "apiServerVersion: 1.14" \
  -H "Content-Type: application/json" \
  -d '{
    "storeTrxDetails": {
        "storeId": 1050,
        "retailerId": 999,
        "basketId": "basket1"
    },
    "dateFrom": "2024-01-01 00:00:00",
    "dateTo": "2024-12-31 23:59:59",
    "pageSize": 10,
    "pageOffset": 0
}'

Get Single Transaction Details

Retrieve detailed information about a specific transaction by its ID.

curl -X POST "https://rad2.wigroup.co:8181/wigroup-transactionengine/pos-providers/transaction-history/v2" \
  -H "id: {posId}" \
  -H "password: {posPassword}" \
  -H "apiClientVersion: {apiClientVersion}" \
  -H "apiServerVersion: 1.14" \
  -H "Content-Type: application/json" \
  -d '{
    "storeTrxDetails": {
        "storeId": 1050,
        "retailerId": 999
    },
    "transactionId": 431711
}'

User Token (Multi-Item Redemption)

Create a merged token that combines multiple coupons, vouchers, and gift cards for a single user. The system redeems coupons first, then vouchers, then deducts from gift cards.

curl -X POST "https://za-vsp-int.wigroup.co/cvs-issuer/rest/users/{userRef}/token" \
  -H "apiId: {apiId}" \
  -H "apiPassword: {apiPassword}" \
  -H "Content-Type: application/json" \
  -d '{
    "couponCampaignIds": [
        "-1"
    ],
    "giftcardIds": [
        "-1"
    ],
    "campaignType": "COUPONVOUCHER"
}'

Tip: Use ["-1"] as a wildcard to include all available items in each category, or specify individual IDs for precise control.

Bills API (QR Code Payments)

Create a bill with a QR code for sit-down payments. Customer scans the QR to pay from their mobile wallet.

curl -X POST "https://rad2.wigroup.co:8181/wigroup-bill/bills" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 2300,
    "basketId": "9eebc2fd-0d26-4680-b54e-f1d66862569b",
    "cashierId": "Cashier1",
    "storeId": "1050",
    "posId": "POS1",
    "basket": [
        {
            "product": {
                "sku": "9999",
                "desc": "Espresso",
                "qty": 1,
                "price": 2300
            }
        }
    ]
}'

Coupon Redemption with Itemised Discounts

When a basket qualifies for multiple product coupons, each one is returned as its own entry in discount. Use this to itemise savings on the till slip.

Transaction Response — coupon redemption
{
  "PosProviderTransactionResponse": {
    "responseCode": "-1",
    "responseDesc": "Success",
    "statusCode": "200",
    "token": {
      "id": "1234567",
      "type": "WICODE",
      "payload": null
    },
    "type": "PAYMENT",
    "storeTrxDetails": {
      "storeId": "1050",
      "remoteStoreId": "store567x",
      "retailerId": "999",
      "basketId": "basket1",
      "trxId": "12345",
      "posId": "POS1",
      "cashierId": "Cashier1",
      "billId": null,
      "posBillId": null
    },
    "switchTrxId": "9876543",
    "wiTrxId": "431711",
    "totalAmountProcessed": "4100",
    "basketAmountProcessed": "4100",
    "cashbackAmountProcessed": "0",
    "tipAmountProcessed": "0",
    "amountToSettle": null,
    "billAmount": null,
    "vsp": {
      "id": "20016",
      "name": "wiCoupon",
      "message": null,
      "trxId": "569023",
      "responseCode": "-1",
      "responseDesc": "Success",
      "balances": null,
      "coupons": null,
      "hasVoucher": null,
      "hasCoupon": null,
      "hasWallet": null,
      "hasGiftCard": null,
      "vspRef": "CVS_20260827164349_0000001"
    },
    "discount": [
      {
        "name": "Parmalat Everfresh Milk 6 x 1L (All Variants)",
        "amount": "2000",
        "product": [
          { "id": "6002100140598", "units": "1", "discount": null }
        ]
      },
      {
        "name": "Five Roses Teabags 100s",
        "amount": "1000",
        "product": [
          { "id": "6001156230253", "units": "1", "discount": null }
        ]
      },
      {
        "name": "Black Cat Peanut Butter 400g (All Variants)",
        "amount": "500",
        "product": [
          { "id": "6009522310301", "units": "1", "discount": null }
        ]
      },
      {
        "name": "Status Roll On 50ml (All Variants)",
        "amount": "300",
        "product": [
          { "id": "6009523605666", "units": "1", "discount": null }
        ]
      },
      {
        "name": "Sunlight Laundry Bar 250g",
        "amount": "300",
        "product": [
          { "id": "6001085041128", "units": "1", "discount": null }
        ]
      }
    ],
    "loyalty": [],
    "balance": []
  }
}
discount[].name

The campaign name. Safe to print on the slip as the customer-facing saving.

discount[].amount

Value of that single discount in cents. The entries sum to totalAmountProcessed.

discount[].product[]

The basket lines the discount applied to, identified by barcode, so you can attach each saving to the right item.

Transaction Webhooks

Configure a callback URL to receive notifications when transactions complete. Useful for sit-down payments and async processing.

Webhook Payload
# Webhook POST to your endpoint
{
  "transactionId": 431711,
  "basketId": "basket1",
  "storeId": 1050,
  "totalAmountProcessed": 10000,
  "state": "S"
}

# Expected response: HTTP 200 OK
Transaction States
  • S - Success
  • F - Failed
  • R - Reversed

Ready to integrate?

Contact our integration team to get your API credentials and sandbox access.

Get API Access