API reference

Mailing lists & subscribers

Manage your audience: lists, the subscribers on them, segments, and custom fields. Paths are relative to https://app.blacklistguard.com/api/v1.

Lists

GET    /mailing-lists
POST   /mailing-lists
PUT    /mailing-lists/{id}
DELETE /mailing-lists/{id}
GET    /mailing-lists/stats?window=30

Create a list with:

FieldDescription
nameList name.
descriptionOptional description.
from_name / from_emailDefault sender for campaigns to this list.
reply_to_emailDefault reply-to.
opt_in_typeOpt-in label for your reference: single, double, api, or import.

stats returns per-list metrics over the window: new_subscribers, unsubscribed, net_growth, engagement_rate, bounce_rate, complaint_rate (rates are 0–1 fractions), health_score (0–100), a daily sparkline, and the last_campaign. Match each row to a list by id.

Subscribers (per list)

GET    /mailing-lists/{id}/subscribers?page&limit&status&search
POST   /mailing-lists/{id}/subscribers
PUT    /mailing-lists/{id}/subscribers/{subscriber_id}
DELETE /mailing-lists/{id}/subscribers/{subscriber_id}
PUT    /mailing-lists/{id}/subscribers/{subscriber_id}/status
DELETE /mailing-lists/{id}/subscribers/all

Add a subscriber with { email, first_name, last_name, source, custom_fields }. On update, email is not editable; you can change first_name, last_name, status, and custom_fields. status is one of active, unsubscribed, bounced, complained.

In the list endpoints, {subscriber_id} is the subscriber's UUID (not the membership row id), and each returned row's custom_fields is a JSON string — parse it before use.

Import & export

POST /mailing-lists/{id}/subscribers/import-async   (multipart, field "csvFile")
POST /mailing-lists/{id}/subscribers/export-async

Both run as background jobs and return a job_id — track progress via the jobs endpoints. The import CSV needs a header row with an Email column; First/Last/Status are optional and extra columns map to the list's defined custom fields.

Subscribers (workspace-wide)

GET /subscribers?page&limit&status&search&list_id
GET /subscribers/{id}
GET /subscribers/{id}/segments

Lists every subscriber across the workspace with a summary and pagination (here custom_fields is a JSON object). get(id) returns full detail: identity, the lists they're on, lifetime stats, an engagement score, recent activity, and their bounces.

Segments

GET    /segments?page&limit&search&list_id
GET    /mailing-lists/{id}/segments
POST   /mailing-lists/{id}/segments
PUT    /mailing-lists/{id}/segments/{segment_id}
DELETE /mailing-lists/{id}/segments/{segment_id}
POST   /mailing-lists/{id}/segments/preview
GET    /mailing-lists/{id}/segments/{segment_id}/subscribers

A segment is a saved filter on a list. Create one with { name, description, conditions, is_active }. conditions uses a recursive { logic, rules } shape — logic is "and" or "or", and each rule is either a condition { field, operator, value } or a nested group with the same { logic, rules } shape:

{
  "logic": "and",
  "rules": [
    { "field": "country", "operator": "equals", "value": "US" },
    { "logic": "or", "rules": [
      { "field": "plan", "operator": "equals", "value": "growth" },
      { "field": "plan", "operator": "equals", "value": "scale" }
    ] }
  ]
}

preview takes the same conditions and returns { subscriber_count } without saving. Note is_active defaults to false unless you set it.

Rule operators

OperatorValueUse for
equals, not_equals, contains, starts_with, ends_withstringText fields
greater_than, less_than, greater_than_or_equal, less_than_or_equalnumberNumeric fields
before, afterdate / datetime stringDate fields
in_last_days, not_in_last_daysinteger (days)Date fields
inarray of stringsText / select
is_one_of, is_not_one_ofarray of stringse.g. email-domain match
ends_with_any_of, does_not_end_with_any_ofarray of stringsSuffix match
is, is_notscalarStatus / boolean fields
is_in, is_not_ina segment idSegment membership
is_active_in, is_not_active_ina mailing-list idActive membership in a list

Custom fields

GET    /mailing-lists/{id}/custom-fields
POST   /mailing-lists/{id}/custom-fields
PUT    /mailing-lists/{id}/custom-fields/{field_id}
DELETE /mailing-lists/{id}/custom-fields/{field_id}

GET    /custom-fields/global   (workspace-wide fields)

Required: field_name, field_label, field_type. The field_name is normalized (lowercased, spaces become underscores) and locked once created. field_type is one of text, textarea, number, date, email, url, boolean, select, multiselect; for select and multiselect you must also supply field_options (a JSON array of choices). Optional: placeholder, default_value, help_text, validation_rules, is_required, is_active, display_order. Global fields apply to every list.