BarsAPI Docsapi.bars.credit

Pay via BARS

BARS are prepaid barcode vouchers. A platform accepts them at checkout by calling this API from its server: validate a code, deduct an amount, and release the goods. It's code-based, not redirect-based — no bouncing the customer to a gateway.

The recommended flow is two calls:

  1. 1POST /v1/verify — is the code valid and in scope? Returns the balance. No money moves.
  2. 2POST /v1/redeem — atomically deducts the amount and returns the new balance + a rotated remaining code. Success → release the goods.

reverse refunds, and a redemptions/{id} lookup reconciles a lost response. All amounts are in major units (e.g. PKR 5000, not paisa).

Environments & keys

Two isolated environments. The key you use decides which one you touch.

EnvBase URLSecret key prefix
Livehttps://api.bars.creditbars-live-…
Sandboxhttps://sbx-api.bars.creditbars-test-…
Test keys only ever touch sandbox bars, and live keys only live bars — they can never cross. Grab both key pairs from the merchant console at merchants.bars.credit.

Authentication

Every call carries your secret key as a bearer token. Keep it server-side — never ship it to a browser or app. Your publishable key (bars-live-pub-…) is the only one safe for clients, and it only identifies you.

Authorization: Bearer bars-live-3f9c…

Signing & idempotency

Money-moving calls (redeem, reverse) additionally require an HMAC signature and a mandatory idempotency key.

  • Idempotency-Key — a unique id per logical payment. Retrying with the same key replays the original result instead of charging twice.
  • X-BARS-Timestamp — unix seconds. Rejected if more than 5 minutes off (replay guard).
  • X-BARS-Signature — HMAC-SHA256(signing_secret, "{timestamp}.{raw_body}"), hex. Sign the exact bytes you send.
X-BARS-Timestamp: 1737480000
X-BARS-Signature: 9a1f…    // hex(hmac_sha256(secret, timestamp + "." + rawBody))
Idempotency-Key: 3b1e2a70-…

Verify

POST/v1/verify

Advisory — checks validity/scope and returns the balance. No deduction.

POST https://api.bars.credit/v1/verify
Authorization: Bearer bars-live-…
Content-Type: application/json

{ "code": "BARS-7F3K-9QP2-4M1X-8ZQ0", "currency": "PKR" }
200 OK
{
  "valid": true,
  "livemode": true,
  "tier": "gold",
  "currency": "PKR",
  "balance": 5000,
  "face_value": 5000,
  "state": "full",
  "expires_at": null
}

Redeem

POST/v1/redeem

Atomic, signed, idempotent. Deducts amount and returns the new balance. On a partial spend the presented code is burned and the leftover rides a new remaining_code (code rotation); null when fully spent. An optional pin is required for PIN-protected bars.

POST https://api.bars.credit/v1/redeem
Authorization: Bearer bars-live-…
Idempotency-Key: 3b1e2a70-…
X-BARS-Timestamp: 1737480000
X-BARS-Signature: 9a1f…
Content-Type: application/json

{ "code": "BARS-7F3K-9QP2-4M1X-8ZQ0", "amount": 1200,
  "currency": "PKR", "merchant_reference": "order_123" }
200 OK
{
  "status": "success",
  "livemode": true,
  "redeemed": 1200,
  "remaining_balance": 3800,
  "remaining_code": "BARS-Z8YD-07D6-K3PN-1AA2",
  "txn_id": "b7e0…",
  "replayed": false
}

Reverse (refund)

POST/v1/reverse

Credits an amount of a redemption back onto a fresh code. Signed + idempotent. Guards: only the redeeming merchant, only up to what was redeemed.

POST https://api.bars.credit/v1/reverse
Authorization: Bearer bars-live-…
Idempotency-Key: c4d2…
X-BARS-Timestamp: 1737480500
X-BARS-Signature: 51ab…

{ "txn_id": "b7e0…", "amount": 1200 }
200 OK
{ "status": "reversed", "livemode": true,
  "credited": 1200, "code": "BARS-4KQ9-2M7P-…", "replayed": false }

Redemption status

GET/v1/redemptions/{txn_id}

Reconcile a redemption whose response you lost. Scoped to your account + mode.

GET https://api.bars.credit/v1/redemptions/b7e0…
Authorization: Bearer bars-live-…
200 OK
{ "txn_id": "b7e0…", "status": "success", "livemode": true,
  "redeemed": 1200, "remaining_balance": 3800,
  "remaining_code": "BARS-Z8YD-…", "created_at": "2026-07-26T14:00:00.000Z" }

Sandbox testing

With a bars-test- key against sbx-api.bars.credit, mint a throwaway bar and run the exact same verify / redeem / reverse flow — no real value at stake.

POST/v1/test/bars
POST https://sbx-api.bars.credit/v1/test/bars
Authorization: Bearer bars-test-…

{ "amount": 500, "currency": "PKR", "tier": "open" }
200 OK
{ "code": "BARS-TEST-…", "tier": "gold", "currency": "PKR",
  "amount": 500, "livemode": false }

Error codes

HTTPerrorMeaning
401unauthorizedMissing or invalid secret key.
401signature_missing / signature_mismatchHMAC signature absent or wrong.
400idempotency_key_requiredMoney-moving call without an Idempotency-Key.
404invalid_codeNo such bar in this mode/scope.
410expiredThe bar has passed its expiry.
403wrong_merchant / gold_not_acceptedBar not accepted by this merchant.
402insufficient_fundsAmount exceeds the balance.
422below_minimumRemainder would fall below the currency minimum.
401pin_requiredBar is PIN-protected; supply pin.
403invalid_pinWrong PIN.
404redemption_not_foundNo such txn for this account/mode.
422exceeds_redeemedReverse amount exceeds what was redeemed.
429rate_limitedToo many requests (120/min per IP).