Globagift Docs
DevelopersAPI reference

Offers

Create, list, update, and change the status of gift card offers (the catalog products customers can buy).

Offers are the catalog products shown as "gift card products" in the dashboard's Gift cards section. All offer endpoints require an authenticated merchant session with the portal.gift_cards permission.

Offers are read from and written to the card network directly

Unlike POS orders and gift cards, offer data is not stored in the portal's own database. List, create, and update all call through to the upstream card network's offer API. The portal's local CatalogOffer table is a separate, partial mirror used elsewhere (for example, to resolve a POS sale); it is not what these endpoints read or write.

List offers

GET /api/bff/offers

Returns all offers for the merchant.

Response

{ "ok": true, "data": { "items": [ ] } }

Each item is an offer object normalised from the upstream response (see Get an offer for the shape).

Create an offer

POST /api/bff/offers

Request body

The request body is passed through to the upstream offer API largely as-is (no fixed schema is enforced beyond "valid JSON object"), with the merchant's upstream merchant ID attached automatically. In practice, the fields used elsewhere in this codebase when building an offer are:

FieldTypeNotes
namestring
descriptionstring
giftCardOfferTypestringFor example GIFTCARD_DIGITAL, REFUND_DIGITAL.
usagestringWhere the offer can be redeemed (web, POS, or both).
typestring
defaultPricenumberUsed for fixed pricing.
minPrice / maxPricenumberUsed for variable (flexible) pricing.
priceLockedboolean
availableForPurchaseTime / expireForPurchaseTimestringSales period bounds.
unlimitedbooleanWhether the sales period is unlimited.
numberOfDaysCardIsValidFromPurchaseTimenumber
denominationsnumber[]Fixed denomination amounts.
currencystring
giftCardDesignarrayDesign image reference(s); see Upload offer media.

Accuracy note

This field list is reconstructed from the update schema used by PUT /api/bff/offers/{id} (see below) and from how the codebase populates an offer elsewhere, since the create route itself accepts an arbitrary object and forwards it upstream. It is a reasonable contract to follow, but it is not enforced by validation on this endpoint the way pos/issue enforces its schema.

Response

{ "ok": true, "data": { } }

data is the created offer, normalised the same way as Get an offer.

Errors

StatusCause
401No session.
404Session user has no associated merchant.
403Session user's role lacks the portal.gift_cards permission.
400Request body is not valid JSON.
variesUpstream create failures pass through the upstream status code with a generic friendly message ("Request failed" for 4xx, "Service unavailable" for 5xx).

Get an offer

GET /api/bff/offers/{id}

Path parameters

ParamRequired
idyes

Response

{
  "ok": true,
  "data": {
    "id": "...",
    "name": "...",
    "status": "...",
    "currency": "...",
    "defaultPrice": 0,
    "min": 0,
    "max": 0,
    "denominations": [],
    "priceLocked": false,
    "availableForPurchaseTime": null,
    "expireForPurchaseTime": null,
    "numberOfDaysCardIsValidFromPurchaseTime": 365,
    "description": null,
    "raw": { }
  }
}

The normaliser tolerates several upstream field-naming variants (for example, accepting defaultPrice, default_price, or faceValue for the default price). raw carries the unmodified upstream response alongside the normalised fields.

Errors

StatusCause
401No session.
404Session user has no associated merchant, or the offer does not belong to this merchant (tenant check).
403Session user's role lacks the portal.gift_cards permission.
400Missing id path parameter.

Update an offer

PUT /api/bff/offers/{id}

Fetches the existing offer first, merges the request body over it (preserving any upstream fields not included in the request), and writes the merged result back upstream. This means a partial update only needs to include the fields being changed.

Request body

All fields optional; unrecognised fields are rejected (.strict() schema).

FieldType
namestring (min length 1)
descriptionstring or null
giftCardOfferStatusstring
usagestring
typestring
defaultPrice / minPrice / maxPricenumber
priceLockedboolean
availableForPurchaseTime / expireForPurchaseTimestring
numberOfDaysCardIsValidFromPurchaseTimenumber
unlimitedboolean
urlGiftcardResourcestring
giftCardDesignarray of objects
denominationsnumber[]
currencystring
id / giftCardOfferId / merchantIdnumber / number / string

Response

{ "ok": true, "data": { } }

Same normalised offer shape as Get an offer.

Errors

StatusCause
401No session.
404Session user has no associated merchant, the offer ID is missing, or the offer does not belong to this merchant (tenant check).
403Session user's role lacks the portal.gift_cards permission.
400Missing id path parameter, or the body contains a field not in the schema above.

Change an offer's status

PATCH /api/bff/offers/{id}/status

A narrower alternative to a full update, for changing only the offer's status.

Request body

FieldTypeRequired
statusstring, one of AVAILABLE, HIDDEN, AWAITING_APPROVAL, CANCELED, EXPIRED, ARCHIVEDyes

Dashboard shows a narrower set

The dashboard's gift card list currently shows offers as available, awaiting approval, or canceled (see the Merchant Guides Gift cards page). The upstream status enum has more values than the dashboard currently surfaces; HIDDEN, EXPIRED, and ARCHIVED are valid values here even though they aren't part of the documented dashboard UI flow.

Response

{ "ok": true, "data": { } }

Errors

Same as Update an offer.

Upload offer media

POST /api/bff/offers/media

Uploads a gift card design image to internal object storage and returns a public URL to reference from an offer's giftCardDesign.

Request

multipart/form-data with a single field:

FieldTypeRequired
filefileyes

Response

{
  "ok": true,
  "data": {
    "urlResource": "https://app.globagift.io/api/public/gift-card-image?key=...",
    "urlImage": "https://app.globagift.io/api/public/gift-card-image?key=...",
    "previewUrl": "https://.../api/public/gift-card-image?key=...",
    "key": "public/gift-cards/designs/<uuid>-<filename>",
    "fileName": "<uuid>-<filename>"
  }
}

urlResource and urlImage use the canonical portal URL (MERCHANT_PORTAL_URL, defaulting to https://app.globagift.io). previewUrl uses the requesting host instead, useful when previewing from a different environment.

Errors

StatusCause
401No session.
404Session user has no associated merchant.
403Session user's role lacks the portal.gift_cards permission.
400No file provided in the form data.
500Upload to storage failed.

On this page