Added

API Updates - March 2026

Exports

Record Limits for Exports and Audience Downloads

Set a maximum number of records returned when downloading audiences or creating/updating exports. The record_limit field accepts a structured object with a cap and a failure mode. To clear a previously set limit on an existing export, set record_limit to null in the update payload.

POST /api/v1/exports
PUT  /api/v1/exports/{id}
GET  /audiences/{id}/download

Parameters (Export create/update body):

  • record_limit (object, optional). Controls max records in export output.
    • maxRecords (int64, 1 to 10,000,000). Maximum records to include.
    • failMode (string). Behavior when the limit is exceeded.

Parameters (Audience download query):

  • project_id (string, required). Workspace project ID.
  • record_limit (int, optional, 0 to 10,000,000). Max records to return. Pass 0 to clear.

Example (set a record limit on export creation):

curl -X POST https://apiv3.delivr.ai/api/v1/exports \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Weekly CRM sync",
    "record_limit": {
      "maxRecords": 50000,
      "failMode": "truncate"
    }
  }'

Example (clear a record limit):

curl -X PUT https://apiv3.delivr.ai/api/v1/exports/exp_abc123 \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"record_limit": null}'

DSP List Name Preservation

When exporting an audience to DelivrDSP, the audience name is automatically used as the DSP list name. Override with a custom name using the list_name field.

POST /api/v1/exports

Parameters (body):

  • list_name (string, optional). Custom DSP list name. Defaults to the audience name if omitted.

Per-Record Export Error Details

Export run responses now include a breakdown of results by CRM object type. The object_type_results map provides per-object success/failure counts and individual error messages for failed records.

GET /api/v1/exports/{id}/runs
GET /api/v1/exports/{id}/runs/{run_id}

Response fields (on export run objects):

  • records_total (int64). Total records processed.
  • records_exported (int64). Successfully exported records.
  • records_failed (int64). Failed records.
  • records_duplicated (int64). Duplicate records skipped.
  • object_type_results (map[string]object). Per-object-type breakdown, keyed by object name (e.g., "Contact", "Lead"):
    • object_type (string). CRM object type name.
    • records_created (int64). New records created.
    • records_updated (int64). Existing records updated.
    • records_failed (int64). Records that failed.
    • records_skipped (int64). Records skipped.
    • operation (string). Operation performed.
    • error_message (string). Error detail for failures.

Example response:

{
  "run_id": "run_xyz789",
  "status": "completed_with_errors",
  "records_total": 5000,
  "records_exported": 4950,
  "records_failed": 50,
  "object_type_results": {
    "Contact": {
      "object_type": "Contact",
      "records_created": 3200,
      "records_updated": 1700,
      "records_failed": 45,
      "records_skipped": 5,
      "operation": "upsert",
      "error_message": "REQUIRED_FIELD_MISSING: Email is required"
    }
  }
}

CRM Field Mapping

Field Constraints and Normalization

CRM exports now validate and normalize field values before pushing to the destination. Each field can have a maximum character length, required flag, allowed picklist values, and type-specific formatting.

Validation error codes:

  • REQUIRED_FIELD_MISSING. A required field has an empty value.
  • STRING_TOO_LONG. Value exceeds the field's maxLength (measured in Unicode runes, not bytes).
  • MULTI_VALUE_TOO_LONG. A multi-value/array field exceeds the destination's length limit after flattening. Previously these were silently truncated.
  • INVALID_PICKLIST_VALUE. Value is not in the allowed picklist (case-insensitive comparison).
  • INVALID_EMAIL_FORMAT. Email field missing @ or ..

Breaking change: Multi-value fields that exceed the destination's character limit now return a MULTI_VALUE_TOO_LONG error instead of being silently truncated. Update your field mappings or reduce the number of values to stay within limits.

Normalization behavior:

  • String values are truncated to maxLength in a Unicode-safe manner (rune-based, not byte-based).
  • Configurable default values are applied when a field is empty.

HubSpot Contact Write with Auto-Created Companies

HubSpot exports now automatically create or attach company records when writing contacts. If a contact's company_domain matches an existing HubSpot company, that company is linked. If no match exists, a new company is created.

Pixel activity from Delivr is also written to the contact's HubSpot timeline, surfacing on-site behavior natively in HubSpot's contact view. No additional configuration is required for existing HubSpot integrations. This behavior is enabled automatically on the next sync.


Audiences and Lists

Bulk Delete for List Uploads

Remove multiple list uploads in a single request.

DELETE /api/v1/lists/batch

Request body:

  • ids (string[], required). Array of list IDs to delete. Maximum 1,000 items per request.

Response:

{
  "deleted_count": 3
}

Type and Source Filters on List Uploads

Filter list upload results by upload type and originating source.

GET /api/v1/lists

Query parameters:

  • type (string, optional). Filter by list type.
  • source (string, optional). Filter by originating source.
  • limit (int, optional, default 25, max 1000). Results per page.
  • offset (int, optional). Pagination offset.

Audience Preview Limit

The audience preview endpoint now accepts a limit query parameter to control the maximum number of preview rows returned, useful when previewing very large audiences.

GET /api/v1/audiences/{id}/preview

Query parameters:

  • limit (int, optional). Maximum number of preview rows to return.

DSP Reporting

Campaign Match Rates

DelivrDSP campaign responses now include match rate data showing how many exported contacts were matched by the DSP.

GET /api/v1/campaigns/{campaign_id}/match-rates

Response:

  • match_rate (float64). Overall match rate as a decimal (e.g., 0.85 for 85%).
  • identifiers_count (int64). Total identifiers sent.
  • matched_count (int64). Identifiers successfully matched.
  • contacts_total (int64). Distinct contacts in the campaign.
  • lists (array). Per-list match breakdown.

Daily Campaign Performance

DelivrDSP campaign performance is now persisted with per-day granularity. Daily delivery, spend, and CPM trends are available through the campaign performance endpoints, alongside the existing cumulative totals.


Privacy and Compliance

UID2 Opt-Out Webhook

A new public webhook endpoint accepts UID2 opt-out notifications. When a user opts out through the UID2 framework, their record is added to a unified privacy opt-out registry with a full audit log. This endpoint does not require JWT authentication.

GET  /api/v1/uid2/optout
POST /api/v1/uid2/optout

Both methods are supported to accommodate different UID2 operator configurations.

Query parameters:

  • user (string, required). UID2 user identifier.
  • optouttime (string, required). ISO 8601 timestamp of the opt-out event.

Response:

  • 204 No Content on success.

Pixel Collection

Cookieless Mode

Organizations can enable cookieless pixel collection through the organization settings API. When cookies_enabled is set to false, pixels deployed for that organization will not set or read browser cookies. Existing pixels are regenerated automatically to reflect the new mode on the next pixel update cycle.

PUT /api/v1/organizations/{id}/settings

Parameters (body):

  • cookies_enabled (bool). Set to false to enable cookieless mode. Defaults to true.

Custom Fields in Pixel Events

Pixel event payloads now include source-level custom fields in the event_data object. This allows richer context from pixel sources to flow into downstream processing.

POST /pixel/core/api/send-event

Request body:

  • pixel_id (string, required). Pixel identifier.
  • organization_id (string, required). Organization ID.
  • event_type (string, required). Event type.
  • event_data (object, optional). Flexible JSON payload. Now includes source-level custom fields alongside standard fields:
    • Geo: country, region, city, coordinates.
    • Device: type, os, browser.
    • Content: title, url, category.
    • Pricing: price, currency.
    • Custom: Any additional key-value pairs defined on the pixel source.

Bug Fixes

  • Export creation with incomplete workspace context. Fixed an issue where export creation could fail with an empty identifier when the workspace context was not fully resolved. The API now returns a 400 with a descriptive error.

  • Email integration test credential error. Fixed email integration test connections returning a credential decryption error.

  • Audience downloads for export-generated lists. Fixed audience downloads failing for lists that were generated by export runs.

  • Campaign sync account filtering. Fixed campaign sync not filtering results by the correct account.

  • Campaign budget and CPM null values. Fixed campaign budget and cpm values being stored as null when syncing from DelivrDSP.

  • record_count field type. Fixed the record_count field being returned as the wrong type in event ingestion responses.

  • Contact database filter casing. Fixed contact database filters using incorrect field name casing.

  • Sync history stuck as RUNNING. Fixed sync history records staying in RUNNING state when the dashboard tab disconnected mid-sync.

  • Empty UUID handling. Fixed empty-string UUID fields being treated as valid IDs in handler responses.


For full endpoint details, parameters, and examples, see our developer documentation.