# List personalized offers

> For the complete machine-readable documentation index, see [llms.txt](https://apidocs.chargebee.com/llms.txt).


This API is used to retrieve a list of personalized offer(s) for a customer based on the context (such as customer or subscription details and end-user attributes). This allows you to retrieve any active offers targeted to the user. You can pre-call this API as soon as you have the user context at the point of login, or can call this API at any other point in the user journey when an offer is to be shown.

System evaluates eligibility and mapping to the right offer based on:

-   Customer profile and subscription information.
-   Device and browsing context.
-   Custom fields.
-   Play configurations.

**Note**

-   Although the response is modeled as a list, the API currently returns at most one personalized offer (the best-matched offer for the user).
-   If no offers are available, the list will be empty. No error is thrown in this case; an empty result is a valid response.

**Features of this API**

The List Personalized Offers endpoint allows you to:

-   Retrieve context-aware offers targeted to customers or end users.
-   Leverage multiple signals (profile, subscription, device/browser context, custom fields, and plays).
-   Call flexibly at login, checkout, renewal, or any point in the user journey.Handle gracefully when no offers are available (returns an empty list, not an error).
-   Support both B2C (single user per customer) and B2B (multiple end users per customer) scenarios.

## Sample Request

#### cURL

```bash
curl  https://{site}.grow.chargebee.com/api/v2/personalized_offers \
     -u {site_api_key}:\
     --header 'Content-Type: application/json;charset=UTF-8' \
     --data '{
     "first_name": "John",
     "last_name": "Doe",
     "email": "john.doe@gmail.com",
     "roles": [
          "admin",
          "engineer"
     ],
     "external_user_id": "abcd",
     "subscription_id": "FfV4CXxpR8nAqB",
     "customer_id": "cb69c692-afd8-43b1-b737-c49e1f6d5fdb",
     "custom": {
          "visit_count": 3,
          "offer_eligible": true
     },
     "request_context": {
          "user_agent": "Mozilla/5.0",
          "locale": "en-US",
          "timezone": "America/Denver",
          "url": "https://www.chargebee.com/pricing/",
          "referrer_url": "https://www.chargebee.com/"
     }
}'
```

#### .NET

```dotnet
using ChargeBee.Api;
using ChargeBee.Models;
using System.Collections.Generic;

ApiConfig.Configure("{site}","{site_api_key}");
var custom = new Dictionary<string, object>();
custom.Add("visit_count", 3);
custom.Add("offer_eligible", true);
EntityResult result = PersonalizedOffer.PersonalizedOffers()
		.FirstName("John")
		.LastName("Doe")
		.Email("john.doe@gmail.com")
		.Roles(new List<string>{"admin", "engineer"})
		.ExternalUserId("abcd")
		.SubscriptionId("FfV4CXxpR8nAqB")
		.CustomerId("cb69c692-afd8-43b1-b737-c49e1f6d5fdb")
		.Custom(custom)
		.RequestContext(new PersonalizedOffer.RequestContextPersonalizedOffersInputParamsBuilder().SetUserAgent("Mozilla/5.0").SetLocale("en-US").SetTimezone("America/Denver").SetUrl("https://www.chargebee.com/pricing/").SetReferrerUrl("https://www.chargebee.com/").Build())
		.Request();

List<PersonalizedOffer> personalizedOffers = result.PersonalizedOffers;
Brand brand = result.Brand;
```

#### Go

```go
package main
import (
    "fmt"
    "github.com/chargebee/chargebee-go/v3"
    personalizedofferAction "github.com/chargebee/chargebee-go/v3/actions/personalizedoffer"
    "github.com/chargebee/chargebee-go/v3/models/personalizedoffer"
)
func main() {
    chargebee.Configure("{site_api_key}","{site}");
    res,err := personalizedofferAction.PersonalizedOffers(&personalizedoffer.PersonalizedOffersRequestParams{
        FirstName : "John",
        LastName : "Doe",
        Email : "john.doe@gmail.com",
        Roles : []string{"admin", "engineer"},
        ExternalUserId : "abcd",
        SubscriptionId : "FfV4CXxpR8nAqB",
        CustomerId : "cb69c692-afd8-43b1-b737-c49e1f6d5fdb",
        Custom : map[string]interface{}{
            "visit_count" : 3,
            "offer_eligible" : true,
        },
        RequestContext : &personalizedoffer.PersonalizedOffersRequestContextParams{
            UserAgent : "Mozilla/5.0",
            Locale : "en-US",
            Timezone : "America/Denver",
            Url : "https://www.chargebee.com/pricing/",
            ReferrerUrl : "https://www.chargebee.com/",
        },
    }).Request()
    if err != nil {
        fmt.Println(err)
    } else {
        PersonalizedOffers := res.PersonalizedOffers
        Brand := res.Brand
    }
}
```

#### Go

```go
package main

import (
  "fmt"
  "github.com/chargebee/chargebee-go/v4"
)

func main() {
  config := &chargebee.ClientConfig{
    SiteName: "{site}",
    ApiKey: "{site_api_key}",
  }    
  client := chargebee.NewClient(config)
  req := &chargebee.PersonalizedOfferPersonalizedOffersRequest{
    FirstName : "John",
    LastName : "Doe",
    Email : "john.doe@gmail.com",
    Roles : []string{"admin", "engineer"},
    ExternalUserId : "abcd",
    SubscriptionId : "FfV4CXxpR8nAqB",
    CustomerId : "cb69c692-afd8-43b1-b737-c49e1f6d5fdb",
    Custom : map[string]interface{}{
        "visit_count" : 3,
        "offer_eligible" : true,
    },
    RequestContext : &chargebee.PersonalizedOfferPersonalizedOffersRequestContext{
        UserAgent : "Mozilla/5.0",
        Locale : "en-US",
        Timezone : "America/Denver",
        Url : "https://www.chargebee.com/pricing/",
        ReferrerUrl : "https://www.chargebee.com/",
    },
}
  res, err := client.PersonalizedOffer.PersonalizedOffers(req)
      if err != nil {
        fmt.Println(err)
    } else {
        PersonalizedOffers := res.PersonalizedOffers
        Brand := res.Brand
    }
}
```

#### Java

```java
import com.chargebee.*;
import com.chargebee.ListResult;
import com.chargebee.models.*;
import com.chargebee.models.enums.*;
import java.io.IOException;
import java.util.List;

public class Sample {

    public static void main(String args[]) throws IOException, Exception {
        Environment.configure("{site}", "{site_api_key}");
        Result result = PersonalizedOffer.personalizedOffers()
            .firstName("John")
            .lastName("Doe")
            .email("john.doe@gmail.com")
            .roles("engineer")
            .externalUserId("abcd")
            .subscriptionId("FfV4CXxpR8nAqB")
            .customerId("cb69c692-afd8-43b1-b737-c49e1f6d5fdb")
            .custom(new java.util.HashMap<String, Object>() {{ put("visit_count", 3); put("offer_eligible", true); }})
            .requestContextUserAgent("Mozilla/5.0")
            .requestContextLocale("en-US")
            .requestContextTimezone("America/Denver")
            .requestContextUrl("https://www.chargebee.com/pricing/")
            .requestContextReferrerUrl("https://www.chargebee.com/")
            .request();

        List<PersonalizedOffer> personalizedOffers = result.personalizedOffers();
        Brand brand = result.brand();
    }
}
```

#### Java

```java
import com.chargebee.v4.client.ChargebeeClient;
import com.chargebee.v4.models.brand.Brand;
import com.chargebee.v4.models.personalizedOffer.PersonalizedOffer;
import com.chargebee.v4.models.personalizedOffer.params.PersonalizedOffersParams;
import com.chargebee.v4.models.personalizedOffer.responses.PersonalizedOffersResponse;
import java.util.List;
import java.util.Map;

public class PersonalizedOffers {

    public static void main(String[] args) {
        ChargebeeClient client = ChargebeeClient.builder()
            .apiKey("{site_api_key}")
            .siteName("{site}")
            .build();

        PersonalizedOffersParams.RequestContextParams requestContextParams =
            PersonalizedOffersParams.RequestContextParams.builder()
                .userAgent("Mozilla/5.0")
                .locale("en-US")
                .timezone("America/Denver")
                .url("https://www.chargebee.com/pricing/")
                .referrerUrl("https://www.chargebee.com/")
                .build();

        PersonalizedOffersParams params = PersonalizedOffersParams.builder()
            .firstName("John")
            .lastName("Doe")
            .email("john.doe@gmail.com")
            .roles(List.of("engineer"))
            .externalUserId("abcd")
            .subscriptionId("FfV4CXxpR8nAqB")
            .customerId("cb69c692-afd8-43b1-b737-c49e1f6d5fdb")
            .custom(Map.of("visit_count", 3, "offer_eligible", true))
            .requestContext(requestContextParams)
            .build();

        PersonalizedOffersResponse response = client.personalizedOffers().personalizedOffers(params);

        List<PersonalizedOffer> personalizedOffers = response.getPersonalizedOffers();
        Brand brand = response.getBrand();
    }
}
```

#### Node.js

```node
import Chargebee from "chargebee";

const chargebee = new Chargebee({
    site: "{site}",
    apiKey: "{site_api_key}",
});

try {
    const result = await chargebee.personalizedOffer.personalizedOffers({
        first_name: "John",
        last_name: "Doe",
        email: "john.doe@gmail.com",
        roles: ["admin", "engineer"],
        external_user_id: "abcd",
        subscription_id: "FfV4CXxpR8nAqB",
        customer_id: "cb69c692-afd8-43b1-b737-c49e1f6d5fdb",
        custom: {
            visit_count: 3,
            offer_eligible: true
        },
        request_context: {
            user_agent: "Mozilla/5.0",
            locale: "en-US",
            timezone: "America/Denver",
            url: "https://www.chargebee.com/pricing/",
            referrer_url: "https://www.chargebee.com/"
        }
    });

    console.log(result);
    const personalizedOffers = result.personalized_offers;
    const brand = result.brand;
} catch (err) {
    console.log(err);
}
```

#### PHP

```php
<?php

require __DIR__ . '/vendor/autoload.php';

use Chargebee\ChargebeeClient;

$chargebee = new ChargebeeClient(options: [
    "site" => "{site}",
    "apiKey" => "{site_api_key}",
]);
$result = $chargebee->personalizedOffer()->personalizedOffers([
    "first_name" => "John",
    "last_name" => "Doe",
    "email" => "john.doe@gmail.com",
    "roles" => ["admin", "engineer"],
    "external_user_id" => "abcd",
    "subscription_id" => "FfV4CXxpR8nAqB",
    "customer_id" => "cb69c692-afd8-43b1-b737-c49e1f6d5fdb",
    "custom" => '{"visit_count":3,"offer_eligible":true}',
    "request_context" => [
        "user_agent" => "Mozilla/5.0",
        "locale" => "en-US",
        "timezone" => "America/Denver",
        "url" => "https://www.chargebee.com/pricing/",
        "referrer_url" => "https://www.chargebee.com/"
    ]
]);
$personalizedOffers = $result->personalized_offers;
$brand = $result->brand;
```

#### Python

```python
from chargebee import Chargebee

cb_client = Chargebee(api_key="{site_api_key}", site="{site}")
response = cb_client.PersonalizedOffer.personalized_offers(
    cb_client.PersonalizedOffer.PersonalizedOffersParams(
        first_name="John",
        last_name="Doe",
        email="john.doe@gmail.com",
        roles=["admin", "engineer"],
        external_user_id="abcd",
        subscription_id="FfV4CXxpR8nAqB",
        customer_id="cb69c692-afd8-43b1-b737-c49e1f6d5fdb",
        custom={
            "visit_count": 3,
            "offer_eligible": True
        },
        request_context=cb_client.PersonalizedOffer.PersonalizedOffersRequestContextParams(
            user_agent="Mozilla/5.0",
            locale="en-US",
            timezone="America/Denver",
            url="https://www.chargebee.com/pricing/",
            referrer_url="https://www.chargebee.com/"
        )
    )
)
personalized_offers = response.personalized_offers
brand = response.brand
```

#### Ruby

```ruby
require 'chargebee'

ChargeBee.configure(:site => "{site}",
  :api_key => "{site_api_key}")

result = ChargeBee::PersonalizedOffer.personalized_offers({
  :first_name => "John",
  :last_name => "Doe",
  :email => "john.doe@gmail.com",
  :roles => ["admin", "engineer"],
  :external_user_id => "abcd",
  :subscription_id => "FfV4CXxpR8nAqB",
  :customer_id => "cb69c692-afd8-43b1-b737-c49e1f6d5fdb",
  :custom => {:visit_count => 3,:offer_eligible => true},
  :request_context => {
    :user_agent => "Mozilla/5.0",
    :locale => "en-US",
    :timezone => "America/Denver",
    :url => "https://www.chargebee.com/pricing/",
    :referrer_url => "https://www.chargebee.com/"
  }
})

personalized_offers = result.personalized_offers
brand = result.brand
```

## Sample Response

```json
{
  "personalized_offers": [
    {
      "id": "a52ge40b",
      "offer_id": "51Ora2PrXz",
      "content": {
        "title": "&lt;div class=\"slate-p\"&gt;Need  to take a break?&lt;/div&gt;",
        "description": "&lt;div class=\"slate-p\"&gt;Instead of canceling why don't you pause your plan? We'll be here when you are ready to get started again.&lt;/div&gt;"
      },
      "options": [
        {
          "id": "af647113-6002-4159-a48a-87f11564963e",
          "label": "PAUSE MY PLAN",
          "processing_type": "url_redirect",
          "redirect_url": "https://mysecurecheckoutflow.com/abcd"
        },
        {..}
      ]
    },
    {..}
  ],
  "brand": {
    "id": "1d5QXw39ar",
    "name": "SecureCheck"
  },
  "expires_at": 24134311
}
```

## URL Format

**POST** https://[site].grow.chargebee.com/api/v2/personalized_offers

## Input Parameters

- `first_name` (optional, string, max chars=150)
  First name of the customer.
  
  **Note**  
  This parameter is ignored if it is not mapped to any field in the [settings](https://www.chargebee.com/docs/retention/chargebee-billing-integration.html#syncing-and-mapping-chargebee-fields-into-chargebee-retention).

- `last_name` (optional, string, max chars=150)
  Last name of the customer.
  
  **Note**  
  This parameter is ignored if it is not mapped to any field in the [settings](https://www.chargebee.com/docs/retention/chargebee-billing-integration.html#syncing-and-mapping-chargebee-fields-into-chargebee-retention).

- `email` (optional, string, max chars=70)
  Customer's email address.
  
  **Note**  
  This parameter is ignored if it is not mapped to any field in the [settings](https://www.chargebee.com/docs/retention/chargebee-billing-integration.html#syncing-and-mapping-chargebee-fields-into-chargebee-retention).

- `roles` (optional, string, max chars=50)
  Roles or user types associated with the end user. (Useful in offer targeting for B2B scenarios with multiple user roles.).
  
  **Note**  
  This parameter is ignored if it is not mapped to any field in the [settings](https://www.chargebee.com/docs/retention/chargebee-billing-integration.html#syncing-and-mapping-chargebee-fields-into-chargebee-retention).

- `external_user_id` (optional, string, max chars=50)
  The unique identifier of the user in the your system. This is used to identify the user for whom the offer is being created.
  
  **Note**  
  This parameter is ignored if it is not mapped to any field in the [settings](https://www.chargebee.com/docs/retention/chargebee-billing-integration.html#syncing-and-mapping-chargebee-fields-into-chargebee-retention).

- `subscription_id` (optional, string, max chars=50)
  The unique identifier of the subscription for which the offer should be retrieved. **Notes:**
  
  -   **Required** if multiple brands are configured in your Growth application.
  -   **Recommended** to always provide.
  -   If omitted and the customer has multiple subscriptions, the system attempts to retrieve the offer associated with one of their subscriptions.

- `customer_id` (required, string, max chars=50)
  The ID of the customer in the billing system (Chargebee customer ID).

- `custom` (optional, jsonobject)
  JSON object of custom attributes (key-value pairs) used for offer targeting or content. [Configure](https://www.chargebee.com/docs/retention/settings-and-installation/chargebee-retention-field-mappings) custom attributes in the dashboard.
  
  **Note**  
  This parameter is ignored if it is not mapped to any field in the [settings](https://www.chargebee.com/docs/retention/chargebee-billing-integration.html#syncing-and-mapping-chargebee-fields-into-chargebee-retention).

- `request_context` (optional, string)
  A JSON object with standard context attributes (browser, device, locale, etc.) of the end user's session. This can help in offer targeting based on user environment.
  - `user_agent` (optional, string, max chars=255)
    The user's browser or device user agent string. Helps determine browser and platform details. For example, chrome/7.10
  - `locale` (optional, string, max chars=50)
    The user's locale setting (e.g., en-US, fr-FR). Useful for regional offer targeting.
  - `timezone` (optional, string, max chars=64)
    The user's timezone identifier (e.g., America/New\_York). Used for contextual targeting based on time.
  - `url` (optional, string, max chars=250)
    The current page URL where the offer is being displayed. Useful for context-sensitive offers.
  - `referrer_url` (optional, string, max chars=250)
    The referring page URL, i.e., the previous page that navigated the user to the current one. Can help with attribution analysis.

## Returns

- `personalized_offers` (always returned)
  List of best offers to be shown to the customer. Currently this will always return one personalized offer. This will be empty if no best offers are found.

- `brand` (Brand object)
  Resource object representing brand

- `expires_at` (required, timestamp(UTC) in seconds)
  The timestamp until which the offer remains active. After this time, you must retrieve the offer again via the List Personalised Offers API to get the latest.
