See also: Contact Policies concept and configuration for what this API powers, when to call it, and how it is configured.
See the Contact Policies feature page for UI guidance and conceptual overview.
Base path
List contact policies
Query parameters
Response 200
Create a contact policy
admin role.
Request body
Rule types and config shapes
Fourteen rule types are supported. Each has a specificconfig object shape:
Campaign-aware
frequency_cap: withinCampaignId (when set) restricts the cap to summary rows whose campaignId matches that batch-run id — other campaigns and non-campaign sends are ignored. excludeCampaignIds drops impressions from the listed campaigns; rows with no campaign attached are still counted. campaignScoped: true marks the cap as per-campaign-run: it only applies while a batch campaign run is evaluating candidates and counts only impressions recorded within that run — real-time /recommend traffic skips the rule entirely (an explicit withinCampaignId still takes precedence over the current run’s id). Interaction history and summaries carry an additive nullable campaignId field populated when one is supplied at send time.offer_category_cap matching: targetCategory is matched case-insensitively against the candidate’s Offer.category marketing string (with a fallback match on the taxonomy categoryId). The interaction-summary store denormalizes Offer.category onto each row, so the cap counts only contacts in the target category. Legacy summary rows written before that denormalization carry a NULL category and are not counted.For
outcome_based rules, config.afterOutcome accepts either a non-empty string (legacy single-outcome form) or a non-empty array of strings (preferred). Empty values are rejected with outcome_based requires afterOutcome as a non-empty string or non-empty string array. config.suppressForDays must be >= 0. The Studio UI exposes a one-click Adverse Outcomes preset that fills the array with ["complaint", "unsubscribe", "hard_bounce", "spam_report"] for the standard 90-day compliance quarantine.Example request
Response 201
Returns the created contact policy object.
Validation
All fields are validated via Zod schemas:name: 1-255 characters, must be unique per tenant.ruleType: Must be one of the fourteen enum values listed above. Forcustomer_total_cap,config.maxTotalis required (non-negative number) andconfig.periodType(if set) must be one ofdaily,weekly,monthly,alltime. Foroffer_category_cap,config.targetCategory(non-empty string) andconfig.maxTotal(non-negative number) are required, andconfig.periodTypefollows the same enum. Forfrequency_cap,config.withinCampaignId(when set) must be a non-empty string,config.excludeCampaignIds(when set) must be a non-empty string array, andconfig.campaignScoped(when set) must be a boolean.scope: Must be one of:global,offer,creative,channel,category,subcategory.priority: Integer, 0-100.config: Free-form JSON object (structural validation per rule type is not enforced by the schema).
Error codes
Update a contact policy
admin role.
Request body
All fields from the create schema are accepted as optional, plus:Example request
Response 200
Returns the updated contact policy object.
Delete a contact policy
draftConfig.
Query parameters
Response 200
This endpoint uses soft-delete — the record is not physically removed from the database. It is excluded from GET results by default. To include soft-deleted records, pass
?includeDeleted=true on the GET request.The API checks all Decision Flows in the tenant for references to this policy ID in their
draftConfig.stages.filter.contactPolicyIds array and returns warnings for any matches.Error codes
Role requirements
Soft-delete and audit
Contact policies use soft-delete with audit snapshots. When a policy is deleted:- The
deletedAttimestamp is set (record is retained). - An audit snapshot is captured with the full state before deletion.
- Ghost reference warnings are returned if the policy is still referenced by any Decision Flow.
- Any materialized suppressions written by this policy (see Suppressions) are removed, and the per-tenant policy cache is invalidated — the policy stops firing on the very next
/recommend, not after a cache TTL. Deactivating a policy (PUTwithstatusother thanactive) clears its suppressions the same way. As a backstop, decision-time suppression reads also ignore any row whose policy is no longer active.
/recommend immediately.
Updates also create audit snapshots via auditedUpdate, incrementing the version field on each change.
To include soft-deleted policies in GET responses, add ?includeDeleted=true to the query string.
Multi-scope policies are evaluated differently: global-scoped policies are evaluated in the Decision Flow’s Filter node, while entity-scoped policies (offer, channel, creative) are automatically evaluated per-candidate during the recommend pipeline.
Preview policy impact
frequency_cap-style policy would have affected
recent traffic. Samples up to 1,000 active customers, counts matching
interactions in the lookback window, and returns affected counts plus an
optional segment breakdown.
Request body
Response 200
frequency_cap config panel. The button derives maxFrequency
and periodDays from the largest cap on the form (daily → 1 day, weekly → 7,
monthly → 30, total → 365).
Contact Policies
Learn more about configuring contact policies in the platform UI.