> For the complete documentation index, see [llms.txt](https://docs.sparkloop.app/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.sparkloop.app/api-v3/objects-schema/offer-recommendation-object.md).

# Offer Recommendation Object

## Offer Recommendation Object

An offer a publication has joined. The full directory offer is always inlined as `offer`.

| Field        | Type   | Description                                    |
| ------------ | ------ | ---------------------------------------------- |
| `uuid`       | String | Offer recommendation UUID.                     |
| `status`     | String | Status of the joined offer.                    |
| `created_at` | String | When the offer was joined (ISO 8601).          |
| `offer`      | Object | The joined offer (**Directory Offer Object**). |
| `stats`      | Object | Performance. Present only with `expand=stats`. |

**`stats`** (only with `expand=stats`)

By default, `stats` is a flat object:

| Field             | Type    | Description                                             |
| ----------------- | ------- | ------------------------------------------------------- |
| `impressions`     | Integer | Times shown.                                            |
| `claims`          | Integer | Primary conversions (claims).                           |
| `claim_rate`      | Number  | Claims / impressions, as a percentage.                  |
| `conversions`     | Integer | Confirmed conversions.                                  |
| `conversion_rate` | Number  | Confirmed conversions / subscriptions, as a percentage. |
| `earnings`        | Number  | Confirmed earnings, in dollars.                         |

**Grouped `stats`** (show only, with `stats_grouped_by`)

On **Get offer**, pass `stats_grouped_by=utm_source`, `utm_campaign`, or `country_code` with `expand=stats` to get the same stats shape nested under each group key. Results are capped at the top 50 groups by impression volume. Blank or missing values appear under `"none"`. Optionally pass `stats_group_value` to return a one-key map for that group only.

**Example (`expand=stats`)**

```json
{
  "uuid": "offrec_5d6e7f",
  "status": "active",
  "created_at": "2026-01-15T09:00:00.000Z",
  "offer": {
    "uuid": "offer_1a2b3c",
    "headline": "Get 20% off Acme Pro",
    "description": "Premium productivity tools for newsletter teams.",
    "terms": "New customers only.",
    "conversion_type": "lead",
    "category": "Productivity",
    "image_url": "https://assets.sparkloop.app/offers/offer_1a2b3c.png",
    "commissions": [ { "type": "fixed_amount", "amount": 2.0, "description": "Per verified lead" } ],
    "geo_restrictions": { "allow_worldwide_referrals": true, "allowed_countries": [], "blocked_countries": [] },
    "source": "external-brand",
    "brand": { "name": "Acme Inc.", "logo_url": "https://assets.sparkloop.app/brands/acme.png" },
    "max_payout": 1000.0
  },
  "stats": {
    "impressions": 4200,
    "claims": 330,
    "claim_rate": 7.86,
    "conversions": 90,
    "conversion_rate": 27.27,
    "earnings": 180.0
  }
}
```

**Example (`expand=stats&stats_grouped_by=utm_source`)**

```json
{
  "uuid": "offrec_5d6e7f",
  "status": "active",
  "created_at": "2026-01-15T09:00:00.000Z",
  "offer": {
    "uuid": "offer_1a2b3c",
    "headline": "Get 20% off Acme Pro",
    "source": "external-brand",
    "brand": { "name": "Acme Inc.", "logo_url": "https://assets.sparkloop.app/brands/acme.png" },
    "max_payout": 1000.0
  },
  "stats": {
    "twitter": {
      "impressions": 3000,
      "claims": 240,
      "claim_rate": 8.0,
      "conversions": 70,
      "conversion_rate": 29.17,
      "earnings": 140.0
    },
    "none": {
      "impressions": 1200,
      "claims": 90,
      "claim_rate": 7.5,
      "conversions": 20,
      "conversion_rate": 22.22,
      "earnings": 40.0
    }
  }
}
```
