Docs/Segments

Segments#

Segments are free-form string labels attached to an order. Karla uses them to decide which campaigns render on the tracking page, and they can also gate shipment-handling rules. A single order can carry any number of segments.

If you run a native shop integration (Shopify, Shopware) you mostly get segments for free from order tags. If you build on the API directly, you send them yourself on the order payload — that's what this page covers.

Where segments come from#

An order's segments are the union of two sources:

  1. Sent by you via the API — the segments array on the order payload.
  2. Populated by Karla's shop integrations, which send segments on the same order payload — the Shopify and Shopware apps both upsert orders, so their segments merge with yours rather than overwriting them:
    • Shopify — each order/customer tag becomes Shopify.tag.<tag>. See Customer segments via order tags.
    • Shopware — tags, customer group, and sales channel become Shopware.tag.<tag>, Shopware.customer_group.<group>, and Shopware.sales_channel.<channel>. See Order segments.
    • Klaviyo — list and segment membership become Klaviyo.list.<name> and Klaviyo.segment.<name> (looked up by customer email).

Both sources land in the same segments list on the order, so a campaign can target a tag you set in Shopify and a segment you pushed via the API interchangeably.

Naming convention#

Karla treats segments as opaque strings — it does not parse or validate them. The dotted Source.type.value shape on integration segments (Shopify.tag.vip, Klaviyo.list.newsletter) is just a convention.

Because your API-supplied segments share the same list as integration-derived ones, the one thing to watch is collisions — pick values that won't accidentally match a segment another connected service emits. Namespacing your own (e.g. tier.gold, erp.region.dach) is an easy way to stay clear, but it's optional. A couple of things to know either way:

  • Segments are case-sensitive and stored verbatim — Karla applies no lowercasing, trimming, or deduplication of values. Integration segments show this too: a Shopware sales channel named Storefront DE becomes the segment Shopware.sales_channel.Storefront DE, spaces and all. VIP and vip are two different segments.
  • There is no enforced length, count, or character limit — but keep them short and machine-readable; you'll be matching them exactly in campaign rules.
  • Don't put PII in segments. They're labels for targeting, not a place for email addresses, names, or order contents.

Sending segments via the API#

segments is an optional array<string> on the order. The endpoint you call decides whether the segments you send are merged with what Karla already knows or replace the list entirely — that's the part to get right.

OperationRequestsegments livesEffect on existing segments
Upsert OrderPUT /v1/shops/{slug}/ordersinside the order objectMerged — union with existing, deduplicated
Place OrderPOST /v1/shops/{slug}/orderstop levelMerged with Karla-derived segments
Fulfill Orders (bulk)PUT /v1/shops/{slug}/orders/bulkinside each orderMerged — same as Upsert
Update OrderPATCH /v1/shops/{slug}/orders/{order_id}top levelReplaced — wholesale, drops everything else

For the complete request and response shapes — required fields, address, products, tracking — follow the matching operation in the API reference. It's generated live from the OpenAPI spec, so it never drifts from the real contract. All four operations authenticate with HTTP Basic auth (your-username:your-private-api-key).

Upsert is the recommended write path: it's keyed by your order_number or external id, so you don't need Karla's internal order id. The segments you send (inside the order object) are unioned with whatever Karla already has, including integration-derived ones — so it's the way to add labels without disturbing the rest.

// PUT /v1/shops/{slug}/orders  — body fragment
{
  "id": "ORD-12345",
  "id_type": "order_number",
  "order": {
    "segments": ["tier.gold", "region.dach"]
    // …plus order_number, address, and the rest of the order fields
  }
}

If the order already had Shopify.tag.vip, after this call it carries Shopify.tag.vip, tier.gold, and region.dach.

Replace the list — Update Order#

PATCH replaces the entire segment list with exactly what you send. Use it to remove a segment or reset an order to a known set. Two things to note:

  • The path takes the Karla order id — the UUID Karla assigns, not your order_number. You'll find it on the order's API record.
  • Omitting segments from the request leaves the existing list untouched (the field is only applied when present).

A PATCH that sends segments overwrites the whole list. If the order had Shopify.tag.* or Klaviyo.* segments, a PATCH that omits them removes them. Send them back explicitly if you want to keep them, or use Upsert to add segments without touching the rest.

Lifecycle#

Segments are not frozen at order creation — Karla re-evaluates them as the order moves through its lifecycle:

  1. At placement — your API-supplied segments plus all integration sources are read.
  2. At every update — re-read from the relevant source (e.g. Shopify order tags from the webhook payload).
  3. At fulfillment — all sources are re-checked. This is the snapshot that decides which campaign the tracking page shows.

The campaign assignment is locked in at fulfillment and won't change afterward, even if a customer's segments change later. For the full evaluation timing — including the Klaviyo one-hour cache — see How segmentation works.

The segment list is stored as an unordered set internally, so don't rely on the order in which segments appear. When an order matches several campaigns, Karla shows the first match it finds.

How segments are used#

  • Campaign targeting — segments select which banner and promotion campaigns render on the tracking page, falling back to the default campaign when nothing matches. See Campaigns.
  • Shipment rules — segments can override whether specific shipments are submitted to carriers.

Because segments cleanly partition your customers, they're also a convenient basis for A/B testing variations of your post-purchase experience.

Was this helpful?