# For developers

Quick guide to integrating Flow Retail's Campaign API into your applications, like for example syncing campaigns from a 3rd party system directly into Flow Retail so that one do not need to add and manage the campaign(s) in Flow Retail.

**Full API reference:** [Campaign API Documentation](https://docs.flowretail.com/api/campaign)

## Quick Start

#### 1. Create a campaign

```bash
POST /v2/tenants/{tenantUid}/campaigns
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json

{
  "name": "3 for 2 T-shirts - Summer 2025",
  "displayName": "3 for 2",
  "type": "CAMPAIGN",
  "discountType": "CHEAPEST_PRODUCT",
  "validFrom": "2025-06-01T00:00:00Z",
  "validTo": "2025-06-30T23:59:59Z",
  "quantityThreshold": 3,
  "discountPercent": 100
}
```

Campaign is created with `status: "NEW"` (not yet active).

#### 2. Add products

```bash
POST /v2/tenants/{tenantUid}/campaigns/{campaignUid}/selections

{
  "create": {
    "include": {
      "categoryUids": ["cat_tshirts"]
    }
  }
}
```

#### 3. Activate

```bash
PUT /v2/tenants/{tenantUid}/campaigns/{campaignUid}

{
  "status": "ACTIVE"
}
```

**Done! Campaign is now live.**

## Key Concepts

### Campaign Types

**CAMPAIGN** - Standard discounts with rules

* Choose discount type: `CHEAPEST_PRODUCT`, `QUALIFIED_PRODUCT`, or `ORDER_DISCOUNT`
* Set conditions: quantity threshold, amount threshold, customer groups
* Most flexible option

**PRICELIST** - Fixed prices from a price list

* Reference an existing price list
* No discount rules, just fixed prices
* Simpler but less flexible

## Common Patterns

### Quantity Discount (3 for 2)

```json
{
  "type": "CAMPAIGN",
  "discountType": "CHEAPEST_PRODUCT",
  "quantityThreshold": 3,
  "discountPercent": 100
}
```

Add products → Activate

### Member Discount (15% for VIP)

```json
{
  "type": "CAMPAIGN",
  "discountType": "QUALIFIED_PRODUCT",
  "discountPercent": 15,
  "customerGroupUid": "group_vip"
}
```

Leave products empty (applies to all) → Activate

#### Spend & Save ($100+ = 10% off)

```json
{
  "type": "CAMPAIGN",
  "discountType": "ORDER_DISCOUNT",
  "amountThreshold": 100.00,
  "discountPercent": 10
}
```

Don't add products (order-level) → Activate

## Important Rules

#### ✅ Valid Combinations

* `CHEAPEST_PRODUCT` + `quantityThreshold` ✅
* `QUALIFIED_PRODUCT` + `quantityThreshold` ✅
* `ORDER_DISCOUNT` + `amountThreshold` ✅
* Any discount type + `customerGroupUid` ✅
* Any discount type + `maxUsage` ✅

#### ❌ Invalid Combinations

* `ORDER_DISCOUNT` + product selections ❌ (order-level discount applies to everything)
* `discountAmount` + `discountPercent` ❌ (choose one)
* Using `quantityThreshold` and `amountThreshold` together ⚠️ (both must be met)

## Critical Behaviors

#### 1. Confirmed Order Lines

**Problem:** Confirmed order lines cannot receive campaigns.

**Solution:** Don't confirm orders until finalizing the order

#### 2. Scanning Order (for CHEAPEST\_PRODUCT)

**Problem:** Discount is calculated based on scanning order.

**Solution:**

* Allow staff to remove and re-scan items if needed
* System will recalculate with optimal discount

#### 3. Product Selection Timing

Products are resolved when you **activate** the campaign. If you add new products to an included category/brand/product group after activation, they won't be included until you deactivate and reactivate the campaign.

#### 4. Updating Campaigns

When updating, include **ALL** fields that should remain:

```json
PUT /campaigns/{uid}
{
  "storeUids": ["store_1", "store_2"]  // Must include ALL stores
}
```

Missing fields may be removed.

***

## Common Issues

### **Campaign does not apply?**

#### Check:

* Status is `ACTIVE`
* Current date/time is between `validFrom` and `validTo`
* Products are in selections (or selections empty for all products)
* Customer is in `customerGroup` if specified
* Order lines are not confirmed

## Best Practices

### Handle large catalogs efficiently

For 1000+ products with few exceptions, use `exclude` instead of `include`:

```json
{
  "create": {
    "exclude": {
      "productUids": ["prod_1", "prod_2"]  // Just exclude sale items
    }
  }
}
```

Much faster than adding thousands of products to `include`.

### Don't confirm lines early

Keep order lines unconfirmed while the customer is shopping. Confirmed lines cannot receive campaigns and must be deleted and re-added.

```javascript
// ❌ Bad: Confirming during shopping
order.addProduct(product);
order.confirmLine(lineId);  // Too early!

// ✅ Good: Confirm at checkout
order.addProduct(product1);
order.addProduct(product2);
// ... customer continues shopping ...
order.confirmAllLines();  // At final checkout
```

## Need more details?

#### **Full API Documentation**

* [Campaign API Reference](https://docs.flowretail.com/api/campaign) - Complete endpoint documentation
* [Product API](https://docs.flowretail.com/api/products) - Managing products
* [Order API](https://docs.flowretail.com/api/orders) - How campaigns apply to orders
* [Customer Groups API](https://docs.flowretail.com/api/customergroup) - Managing customer segments

#### **Support**

* <support@flowretail.com>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.flowretail.com/docs/extensions-addons/campaign/for-developers.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
