Get Bundles (Purchase Offer)
Resolve a transactable offer for the supplied context. Returns the bundles, calculated prices, applied campaigns, and the offerIdentifier to pass to checkout.
URL
POST /api/c2a/offer/bundles
Request Parameters
Body: GetOfferRequest.
| Name | Type | Description |
|---|---|---|
context | object (GetBundlesContext) | Required. Offer resolution context. |
GetBundlesContext
| Name | Type | Description |
|---|---|---|
customerUrn (alias CU) | string | When set, the engine personalizes pricing, eligibility, and campaign matching. |
promotionCode (alias PC) | string | Optional code; engine attempts to resolve a matching CalculatedCampaign. |
stepIndex (alias SF) | integer | Zero-based step for multi-step funnels. Default 0. |
interactionType (alias IT) | string (EnOfferIntentType) | Required. NewAcquisition, Replace, or RetentionWinback. Drives offer set. |
channel (alias CH) | string (EnSubscriptionChannelProviderFamily) | Force a specific channel (Azotte, InappPlayStore, InappAppStore, ExternalPartner). Auto-resolved when null. |
interactionDate (alias ID) | string (date-time) | For time-sensitive offers / audit. |
interactionMeans (alias IM) | string | Source channel hint (web / mobile / agent). |
customTags (alias CTG) | object (string → string) | Tenant-defined metadata for routing logic. |
storefrontUrn (alias SFU) | string | Conditional. Storefront context. Required for multi-storefront tenants. |
originalSubscriptionIdentifier (alias OSI) | string | Conditional. For Replace / Winback flows — the subscription being replaced. |
clientPlatformType (alias PLT) | string (EnClientPlatformType) | Web (default), Mobile, etc. |
Request Example
{
"context": {
"customerUrn": "cu.00.482",
"promotionCode": "CMP1WKWAFY",
"stepIndex": 0,
"interactionType": "NewAcquisition",
"channel": "Azotte",
"storefrontUrn": "st.00.001",
"clientPlatformType": "Web"
}
}
Response Parameters
GetOfferResponse.
| Name | Type | Description |
|---|---|---|
status | object (AzotteStatus) | SUCCESS on hit. |
offer | object (PurchaseOffer) | Resolved offer; null on failure. |
offer.offerIdentifier | string | Pass back to checkout as Order.OfferIdentifier. |
offer.expiresAt | string (date-time) | Offer validity window. Expired offers rejected at checkout. |
offer.productGroupType | string (EnProductGroupType) | RecurringSubscription, OneTime, etc. |
offer.channel | string (EnSubscriptionChannelProviderFamily) | Resolved channel. |
offer.interactionType | string (EnOfferIntentType) | Echo of input intent. |
offer.storefrontUrn | string | Storefront in scope. |
offer.campaign | object (CalculatedCampaign) | Applied campaign + impacts (discount, free period, etc.). |
offer.artifactGroups | array (CalculatedArtifactGroup[]) | Bundles + their calculated prices and add-ons. |
offer.options | object (OfferOptions) | Caller-facing rules (e.g. payment methods allowed). |
offer.stepInfo | object (OfferStepInfo) | Multi-step funnel position. |
offer.presentationType | string (EnOfferPresentationType) | Offer by default. |
offer.presentation | string | Optional rendering payload. |
diagnostics | object (OfferDiagnostics) | Why this offer was returned: matched rules, applied campaigns, eligibility checks. |
Sample Response
{
"status": { "messageCode": "SUCCESS" },
"offer": {
"offerIdentifier": "of_8z2k1q",
"expiresAt": "2026-05-25T12:30:00Z",
"productGroupType": "RecurringSubscription",
"channel": "Azotte",
"interactionType": "NewAcquisition",
"storefrontUrn": "st.00.001",
"campaign": { "code": "CMP1WKWAFY", "name": "May Promo", "discountPercent": 20 },
"artifactGroups": [
{
"bundleUrn": "bn.00.42",
"name": "Pro Monthly",
"price": { "amountMilpieces": 1499, "currency": "EUR" },
"items": [ { "itemIdentifier": "it_ab1", "sku": "PRO-M-1", "quantity": 1 } ]
}
],
"options": { "allowedPaymentMethods": ["CARD", "SEPA"] }
},
"diagnostics": { "matchedRules": ["new-customer-de"], "appliedCampaigns": ["CMP1WKWAFY"] }
}
Sample Codes
- cURL
- JavaScript
- Node.js
- Python
- Java
- C#
- PHP
- Go
curl --location 'https://acme.sandbox.azotte.com/api/v1/c2a/offer/bundles' \
--header 'Content-Type: application/json' \
--header 'x-tn: e2a1c7b2-4f3a-4b8e-9c2d-1a2b3c4d5e6f' \
--header 'x-api-key: sk_dev_acme_sample_123456789' \
--data '{
"context": {
"customerUrn": "cu.00.482",
"promotionCode": "CMP1WKWAFY",
"interactionType": "NewAcquisition",
"channel": "Azotte",
"storefrontUrn": "st.00.001"
}
}'
const payload = {
context: {
customerUrn: 'cu.00.482',
promotionCode: 'CMP1WKWAFY',
interactionType: 'NewAcquisition',
channel: 'Azotte',
storefrontUrn: 'st.00.001'
}
};
const res = await fetch('https://acme.sandbox.azotte.com/api/v1/c2a/offer/bundles', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-tn': 'e2a1c7b2-4f3a-4b8e-9c2d-1a2b3c4d5e6f',
'x-api-key': 'sk_dev_acme_sample_123456789'
},
body: JSON.stringify(payload)
});
console.log(await res.json());
import { request } from 'undici';
const payload = {
context: {
customerUrn: 'cu.00.482',
promotionCode: 'CMP1WKWAFY',
interactionType: 'NewAcquisition',
channel: 'Azotte',
storefrontUrn: 'st.00.001'
}
};
const { body } = await request('https://acme.sandbox.azotte.com/api/v1/c2a/offer/bundles', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-tn': 'e2a1c7b2-4f3a-4b8e-9c2d-1a2b3c4d5e6f',
'x-api-key': 'sk_dev_acme_sample_123456789'
},
body: JSON.stringify(payload)
});
console.log(await body.json());
import requests
payload = {
"context": {
"customerUrn": "cu.00.482",
"promotionCode": "CMP1WKWAFY",
"interactionType": "NewAcquisition",
"channel": "Azotte",
"storefrontUrn": "st.00.001",
}
}
res = requests.post(
"https://acme.sandbox.azotte.com/api/v1/c2a/offer/bundles",
headers={
"Content-Type": "application/json",
"x-tn": "e2a1c7b2-4f3a-4b8e-9c2d-1a2b3c4d5e6f",
"x-api-key": "sk_dev_acme_sample_123456789",
},
json=payload,
)
print(res.json())
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
String json = """
{
"context": {
"customerUrn": "cu.00.482",
"promotionCode": "CMP1WKWAFY",
"interactionType": "NewAcquisition",
"channel": "Azotte",
"storefrontUrn": "st.00.001"
}
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://acme.sandbox.azotte.com/api/v1/c2a/offer/bundles"))
.header("Content-Type", "application/json")
.header("x-tn", "e2a1c7b2-4f3a-4b8e-9c2d-1a2b3c4d5e6f")
.header("x-api-key", "sk_dev_acme_sample_123456789")
.POST(HttpRequest.BodyPublishers.ofString(json))
.build();
HttpResponse<String> res = client.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(res.body());
using System.Net.Http.Json;
var payload = new {
context = new {
customerUrn = "cu.00.482",
promotionCode = "CMP1WKWAFY",
interactionType = "NewAcquisition",
channel = "Azotte",
storefrontUrn = "st.00.001"
}
};
using var http = new HttpClient();
http.DefaultRequestHeaders.Add("x-tn", "e2a1c7b2-4f3a-4b8e-9c2d-1a2b3c4d5e6f");
http.DefaultRequestHeaders.Add("x-api-key", "sk_dev_acme_sample_123456789");
var res = await http.PostAsJsonAsync(
"https://acme.sandbox.azotte.com/api/v1/c2a/offer/bundles",
payload);
Console.WriteLine(await res.Content.ReadAsStringAsync());
<?php
$payload = [
'context' => [
'customerUrn' => 'cu.00.482',
'promotionCode' => 'CMP1WKWAFY',
'interactionType' => 'NewAcquisition',
'channel' => 'Azotte',
'storefrontUrn' => 'st.00.001',
],
];
$ch = curl_init('https://acme.sandbox.azotte.com/api/v1/c2a/offer/bundles');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'x-tn: e2a1c7b2-4f3a-4b8e-9c2d-1a2b3c4d5e6f',
'x-api-key: sk_dev_acme_sample_123456789',
],
CURLOPT_POSTFIELDS => json_encode($payload),
]);
echo curl_exec($ch);
curl_close($ch);
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
func main() {
payload := map[string]any{
"context": map[string]string{
"customerUrn": "cu.00.482",
"promotionCode": "CMP1WKWAFY",
"interactionType": "NewAcquisition",
"channel": "Azotte",
"storefrontUrn": "st.00.001",
},
}
body, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST",
"https://acme.sandbox.azotte.com/api/v1/c2a/offer/bundles",
bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("x-tn", "e2a1c7b2-4f3a-4b8e-9c2d-1a2b3c4d5e6f")
req.Header.Set("x-api-key", "sk_dev_acme_sample_123456789")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
out, _ := io.ReadAll(res.Body)
fmt.Println(string(out))
}