Skip to main content

Offers API

Complete API reference for managing offer templates in the Billerang catalog.

Overview

An OfferTemplate is the top-level catalog entity that groups products/services into sellable bundles. Offers define what a customer can subscribe to and at what terms.

Endpoints

List Offers

GET /v1/catalog/offers?range=0-24&status=active

Query Parameters:

ParameterTypeDescription
rangestringPagination range (e.g., 0-24)
statusstringFilter by status: draft, ready, live, retired
categorystringFilter by category code
sellerstringFilter by seller code
sortstringSort field (prefix - for descending)
fieldsstringPartial response fields
expandstringRelated entities to include

Response:

[
{
"code": "SAAS_ENTERPRISE",
"name": "Enterprise SaaS Plan",
"status": "active",
"valid_from": "2024-01-01T00:00:00Z",
"valid_to": null,
"product_codes": ["PROD_PLATFORM", "PROD_SUPPORT"],
"category_codes": ["ENTERPRISE"],
"seller_codes": ["SELLER_EU"]
}
]

Headers:

Content-Range: offers 0-24/142
Accept-Range: offers 50
Link: </v1/catalog/offers?range=25-49>; rel="next"

For complex queries, use the search DSL:

POST /v1/catalog/offers/search
{
"filters": {
"status": ["active", "launched"],
"valid_from": { "gte": "2024-01-01" },
"product_codes": { "contains": "PROD_PLATFORM" }
},
"sort": ["-created_at"],
"range": "0-24",
"expand": ["products"]
}

Get Offer

GET /v1/catalog/offers/{code}

Response:

{
"code": "SAAS_ENTERPRISE",
"name": "Enterprise SaaS Plan",
"description": "Full platform access with premium support",
"status": "active",
"valid_from": "2024-01-01T00:00:00Z",
"valid_to": null,
"product_codes": ["PROD_PLATFORM", "PROD_SUPPORT"],
"category_codes": ["ENTERPRISE"],
"seller_codes": ["SELLER_EU"],
"discount_plan_codes": ["DISC_ANNUAL_10"],
"auto_end_of_engagement": false,
"attributes": {
"min_commitment_months": 12,
"max_users": 500
}
}

With ?expand=products:

{
"code": "SAAS_ENTERPRISE",
"name": "Enterprise SaaS Plan",
"products": [
{
"code": "PROD_PLATFORM",
"name": "Platform Access",
"product_line": "SOFTWARE",
"current_version": {
"version": 2,
"status": "published",
"charge_codes": ["RC_PLATFORM_MONTHLY", "OS_SETUP_FEE"]
}
},
{
"code": "PROD_SUPPORT",
"name": "Premium Support",
"product_line": "SERVICES",
"current_version": {
"version": 1,
"status": "published",
"charge_codes": ["RC_SUPPORT_MONTHLY"]
}
}
]
}

Create Offer

POST /v1/catalog/offers
{
"code": "SAAS_ENTERPRISE",
"name": "Enterprise SaaS Plan",
"description": "Full platform access with premium support",
"product_codes": ["PROD_PLATFORM", "PROD_SUPPORT"],
"category_codes": ["ENTERPRISE"],
"seller_codes": ["SELLER_EU"]
}

Response: 201 Created + Location: /v1/catalog/offers/SAAS_ENTERPRISE

Upsert Offer

POST /v1/catalog/offers/{code}
  • If offer exists: updates it (200 OK)
  • If offer doesn't exist: creates it with that code (201 Created)

Supports newCode field to rename the offer's code:

{
"newCode": "SAAS_ENTERPRISE_V2",
"name": "Enterprise SaaS Plan v2",
"product_codes": ["PROD_PLATFORM_V2", "PROD_SUPPORT"]
}

Update Offer

PUT /v1/catalog/offers/{code}

Partial update -- only send fields you want to change:

{
"name": "Updated Enterprise Plan",
"status": "launched"
}

Delete Offer

DELETE /v1/catalog/offers/{code}

Response: 204 No Content

Only allowed for offers in draft status. Active/launched offers must be retired first.

Manage Products

Add product to offer:

POST /v1/catalog/offers/{code}/products
{ "product_code": "PROD_ADDON_ANALYTICS" }

Remove product from offer:

DELETE /v1/catalog/offers/{code}/products/{product_code}

Count

GET /v1/catalog/offers/count?status=active

Response:

{ "count": 42 }

Bulk Operations

POST /v1/catalog/offers/bulk
{
"operations": [
{
"action": "create",
"body": { "code": "OFFER_A", "name": "Plan A", "product_codes": ["PROD_1"] }
},
{
"action": "upsert",
"code": "OFFER_B",
"body": { "name": "Updated Plan B" }
},
{
"action": "delete",
"code": "OFFER_OLD"
}
]
}

Offer Lifecycle

Portal status mapping:

Portal StatusBackend Statuses
draftIN_STUDY, IN_DESIGN, IN_TEST
readyACTIVE
liveLAUNCHED
retiredRETIRED, OBSOLETE, REJECTED

Offer Components

Offers group products through two models:

Products are linked via OfferComponent with CPQ product references:

{
"code": "SAAS_ENTERPRISE",
"products": [
{
"code": "PROD_PLATFORM",
"mandatory": true,
"default_quantity": 1,
"min_quantity": 1,
"max_quantity": 1
},
{
"code": "PROD_ADDON",
"mandatory": false,
"default_quantity": 0,
"min_quantity": 0,
"max_quantity": 10
}
]
}

OLD Model (Legacy)

Services linked via OfferServiceTemplate -- still supported for backward compatibility.

Error Codes

Error CodeHTTPDescription
OFFER_NOT_FOUND404Offer code doesn't exist
OFFER_ALREADY_EXISTS409Duplicate offer code
OFFER_VALIDATION_FAILED400Invalid payload
OFFER_STATUS_TRANSITION_INVALID422Invalid status change
OFFER_HAS_ACTIVE_SUBSCRIPTIONS422Cannot delete offer with active subscriptions