Schemas
Every schema of the OpenAPI document, by name. A tree shows one level; a field of another schema links to its entry.
AddSendingDomainRequest
A new sending domain.
- object
-
Who applies the records:
porkbun, ormanualfor entry by hand.- porkbun
- manual
-
domainstringrequiredThe domain of the sender addresses: a host name, a subdomain or an international name (kept in punycode).
example
news.example.com -
bounce_subdomainstringThe domain of the return path (
MAIL FROM), belowdomain; left out:bounce.<domain>.example
bounce.news.example.com -
dkim_selectorstringThe DKIM selector: labels of letters, digits and inner hyphens, at most 63 characters; left out:
pw1.example
pw1 -
ip_poolstringThe IP pool of the node’s config to send from (
GET /api/v1/serverlists them); left out:default.example
default -
tracking_hoststring | nullA host for tracking and unsubscribe links;
nullor left out: none (links use the node’sweb.public_url).example
links.example.com
Used by: add_sending_domain (request)
AddedSendingDomain
A sending domain just added, and the records to create for it.
- object · extends SendingDomain · all fields required
-
bounce_subdomainstringexample
bounce.news.example.com -
checksarray of DomainCheckOne entry per check that ran, in the canonical order; empty until the domain is first verified.
see DomainCheck
-
created_atstring · date-time -
dkim_public_keystringThe DKIM public key: base64 of its DER
SubjectPublicKeyInfo, thep=of the DKIM record (RSA 2048). -
dkim_selectorstringexample
pw1 -
dns_providerDnsProviderWho applies a domain’s DNS records.
- porkbun
- manual
-
domainstringIn punycode for an international name.
example
news.example.com -
idstring · uuidexample
01900000-0000-7000-8000-000000000001 -
ip_poolstringexample
default -
last_checked_atstring · date-time | nullWhen the records were last checked (RFC 3339);
nulluntil then. -
project_idstring · uuid -
required_recordsarray of RequiredRecordWhat to create in DNS, in this order.
see RequiredRecord
-
statusDomainStatusWhere a sending domain stands.
- pending
- verified
- failed
-
tracking_hoststring | nullnull: none. -
updated_atstring · date-time
Used by: add_sending_domain (201)
ApiKey
An API key, without its secret.
- object · all fields required
-
created_atstring · date-time -
expires_atstring · date-time | nullnull: never. -
idstring · uuidWhat revoking the key takes.
example
01900000-0000-7000-8000-000000000001 -
kindApiKeyKindThe kind of an API key.
- admin
- project
-
last_used_atstring · date-time | nullWhen the key was last used;
null: not recorded yet. -
namestringexample
billing backend -
prefixstringThe public part of the key string,
pw_<adm|prj>_<prefix>_...: how to tell which key a client holds.example
1a2b3c4d -
project_idstring · uuid | nullThe key’s project;
nullfor an admin key. -
revoked_atstring · date-time | nullWhen the key was revoked;
nullwhile it is not. -
scopesarray of ScopeWhat the key may do; every scope for an admin key.
ApiKeyKind
The kind of an API key.
string · enum
- admin
- project
ApiKeyList
One page of keys.
- object · all fields required
-
itemsarray of ApiKeyIn id order; revoked and expired keys included.
see ApiKey
-
next_cursorstring | nullPass as
cursorfor the next page;nullon the last page.
Used by: list_admin_keys (200), list_api_keys (200)
AppliedDnsRecord
One required record and what apply did to it.
- object · all fields required
-
contentstringThe value the record should hold.
-
detailstring | nullA message for the outcomes that carry one (
conflict,provider_error,unavailable);nullotherwise. -
namestringThe owner name, without a trailing dot.
example
bounce.news.example.com -
outcomeDnsApplyOutcomeWhat
applydid to one record.- created
- updated
- unchanged
- skipped_exists
- manual
- conflict
- provider_error
- unavailable
-
purposeRecordPurposeWhat a required record is for.
- spf_bounce
- mx_bounce
- dkim
- dmarc
- tracking_cname
-
typeRecordTypeThe type of a DNS record.
- txt
- mx
- cname
AppliedDnsRecords
The result of applying a domain’s DNS records.
- object · all fields required
-
dns_providerDnsProviderWho applied the records:
porkbun, ormanual(nothing was changed; each record’s outcome ismanual).- porkbun
- manual
-
recordsarray of AppliedDnsRecordOne entry per required record, in the order they are created.
see AppliedDnsRecord
Used by: apply_dns_records (200)
Branding
How the public pages look.
- object · all fields required
-
brand_namestring | null -
languageLanguageThe language of the public pages.
- en
- ru
-
support_emailstring · email | null -
text_overridesmap of string → stringTexts of the pages by key.
BrandingInput
Branding of the public pages to set.
- object
-
brand_namestring | nullThe name the pages show, 1 to 128 characters.
-
languagestringenorru.example
ru -
support_emailstring · email | nullThe address the pages give for questions.
-
text_overridesmap of string → stringTexts of the pages by key, replacing every override at once: at most 64, keys
[a-z][a-z0-9_]*, texts 1 to 2000 characters.
Campaign
A campaign of a project.
- object · all fields required
-
completed_atstring · date-time | null -
created_atstring · date-time -
from_emailstring · email | nullnull: the project’ssettings.from_email. -
from_namestring | nullnull: the project’ssettings.from_name. -
idstring · uuidexample
01900000-0000-7000-8000-000000000001 -
last_errorstring | nullWhy the launch failed;
nullunlessfailed. -
launched_atstring · date-time | null -
list_idsarray of stringIn the order given.
-
namestringexample
Spring sale -
partial_versionsmap of string → integer · int32The versions of the partials fixed at launch, by name;
{}before. -
project_idstring · uuid -
reply_tostring · email | nullnull: the project’ssettings.reply_to. -
scheduled_atstring · date-time | nullWhen a scheduled campaign launches;
nullunless scheduled. -
shard_countinteger · int32 | nullFixed at launch;
nullbefore.≥ 0
-
statusstringdraft,scheduled,launching,sending,paused,completed,cancelledorfailed.example
draft -
subject_overridestring | nullnull: the template’s subject. -
template_idstring · uuid -
template_versioninteger · int32 | nullThe template’s version fixed at launch;
nullbefore.≥ 0
-
throttle_per_hourinteger · int32 | nullnull: the project’sdefault_throttle_per_hour, or no limit.≥ 0
-
total_recipientsinteger · int64 | nullRecipients of the launch’s snapshot;
nullbefore.≥ 0
-
tracking_overrideTrackingOverride | nullnull: the project’ssettings.tracking.see TrackingOverride
-
transport_overridestring | nullnull: the project’s transport, then the node’s default. -
updated_atstring · date-timeThe latest change: creation, fields, status.
Used by: create_campaign (201), get_campaign (200), update_campaign (200), cancel_campaign (200), launch_campaign (200), pause_campaign (200), resume_campaign (200)
CampaignDeliveryCounts
How many deliveries of a campaign are in each status; all zero before the launch.
- object · all fields required
-
bouncedinteger · int64Refused for good at
RCPT(a hard bounce).≥ 0
-
cancelledinteger · int64Not sent: the campaign was cancelled.
≥ 0
-
deferredinteger · int64Refused for now; tried again later.
≥ 0
-
failedinteger · int64Refused for good otherwise, out of attempts, or not made.
≥ 0
-
queuedinteger · int64Waiting for their first attempt.
≥ 0
-
sentinteger · int64Taken by the recipient’s server.
≥ 0
-
suppressedinteger · int64Held back by a suppression or the subscriber’s status.
≥ 0
-
totalinteger · int64Every delivery: the sum of the above.
≥ 0
CampaignEventCounts
How many events of a kind a campaign has: every one, and the distinct
subscribers among them (two opens by one subscriber: total 2,
unique 1).
- object · all fields required
-
totalinteger · int64Every event, repeats included.
≥ 0
-
uniqueinteger · int64The distinct subscribers of those events.
≥ 0
CampaignList
One page of campaigns.
- object · all fields required
-
itemsarray of CampaignIn creation order.
see Campaign
-
next_cursorstring | nullPass as
cursorfor the next page;nullon the last page.
Used by: list_campaigns (200)
CampaignPreflight
What a launch of a draft would do now, and what stops it.
- object · all fields required
-
campaign_idstring · uuid -
domainCampaignPreflightDomain | nullThe project’s sending domain of the sender;
nullwhen it has none. -
estimated_duration_secsinteger · int64 | nullHow long sending takes at
throttle_per_hour, in seconds;nullwithout a limit or a count.≥ 0
-
from_emailstring · email | nullThe sender: the campaign’s, else the project’s
settings.from_email;nullwhen neither names one. -
recipientsinteger · int64 | nullRecipients after deduplication and suppression: the deliveries the launch would write.
nullwhen a list is missing or deleted.≥ 0
-
throttle_per_hourinteger · int32 | nullMost messages an hour: the campaign’s, else the project’s
default_throttle_per_hour;null: no limit.≥ 0
-
transportstringThe transport the messages go through:
directorrelay:<name>.example
direct -
violationsarray of ProblemFieldErrorEvery unmet precondition of the launch, as
422 precondition_failedwould list them; empty: it can be launched.
Used by: preflight_campaign (200)
CampaignPreflightDomain
The sending domain of a campaign’s sender.
- object · all fields required
-
domainstringexample
acme.example -
idstring · uuid -
statusstringpending,verifiedorfailed; only averifiedone sends.example
verified -
warningsarray of CampaignPreflightWarningChecks that do not decide the status and are not
ok(ptr,tracking_tls): the launch goes ahead, delivery may suffer.
CampaignPreflightWarning
One check of a preflight’s domain warnings.
- object · all fields required
-
checkstringexample
ptr -
detailstring | null -
statusstringmissing,mismatchorwarning.example
warning
CampaignStats
A campaign’s stats: where its sending is, and its opens and clicks.
- object · all fields required
-
campaign_idstring · uuid -
clicksCampaignEventCountsIts clicks: follows of its tracked links (
message.clicked). -
deliveriesCampaignDeliveryCountsIts deliveries by status.
-
opensCampaignEventCountsIts opens: loads of the open pixel (
message.opened). -
statusstringThe campaign’s status now.
example
sending -
total_recipientsinteger · int64 | nullHow many recipients its launch wrote;
nullbefore the launch.≥ 0
Used by: get_campaign_stats (200)
CheckStatus
How one verification check came out.
string · enum
- ok
- missing
- mismatch
- warning
CreateAdminKeyRequest
A new admin key.
- object
-
namestringrequiredWhat the key is for: 1 to 128 characters, trimmed.
example
ops -
expires_atstring · date-time | nullWhen the key stops working, RFC 3339, later than now;
nullor left out: never.
Used by: create_admin_key (request)
CreateApiKeyRequest
A new project key.
- object
-
namestringrequiredWhat the key is for: 1 to 128 characters, trimmed.
example
billing backend -
What the key may do: at least one scope, each once. A project key grants only scopes it holds itself.
example
["read","write"] -
expires_atstring · date-time | nullWhen the key stops working, RFC 3339, later than now;
nullor left out: never. A project key that expires grants no later expiry.example
2027-01-01T00:00:00Z
Used by: create_api_key (request)
CreateCampaignRequest
A new campaign: a draft. Fields left out or null take the project’s
value when the campaign is launched.
- object
-
list_idsarray of stringrequiredThe lists it goes to: 1 to 16 distinct ids of live lists of the project. A recipient on several is sent once, as a subscriber of the first.
1–16 items
-
namestringrequiredWhat people call the campaign: 1 to 128 characters, trimmed. Two campaigns may share a name.
example
Spring sale -
template_idstring · uuidrequiredThe template it sends: the id of a message template of the project.
-
from_emailstring · email | nullexample
news@acme.example -
from_namestring | nullexample
Acme News -
reply_tostring · email | null -
subject_overridestring | nullThe subject source in place of the template’s.
-
throttle_per_hourinteger · int64 | nullMost messages an hour, 1 to 4294967295.
1–4294967295
-
tracking_overrideTrackingOverrideInput | nullWhat a campaign tracks in place of the project’s
settings.tracking. -
transport_overridestring | nulldirectorrelay:<name>(a relay of the node).example
direct
Used by: create_campaign (request)
CreateListRequest
A new list.
- object
-
namestringrequiredWhat people call the list: 1 to 128 characters, trimmed. Two lists may share a name.
example
Weekly news -
confirmation_template_idstring · uuid | nullThe template of the confirmation letter: the id of a message template of the project; required with
double_opt_in.nullor left out: none. -
double_opt_inbooleanSubscribers confirm by a link before they get campaigns; default
false. Needsconfirmation_template_id. -
from_overrideFromOverrideInput | nullThe sender of the list’s own letters (confirmations) in place of the project’s;
nullor left out: the project’s.
Used by: create_list (request)
CreateProjectRequest
A new project.
- object
-
namestringrequiredWhat people call the project: 1 to 128 characters, trimmed.
example
Acme News -
slugstringrequiredUnique among live projects: 3 to 63 lower-case letters, digits and
-. It never changes.pattern
^[a-z0-9-]{3,63}$· exampleacme-news -
settingsProjectSettingsInputSettings to set; the rest are defaults.
Used by: create_project (request)
CreateSubscriberRequest
A new subscriber, or a re-add of one already on the list.
- object · all fields required
-
attributesobjectAttributes to set: a map of string, number or boolean values.
nullfor a key removes it. Up to 64 keys, up to 4 KB of JSON. -
emailstring · emailThe address; any case and surrounding whitespace are normalized.
example
ann@example.com
Used by: add_subscriber (request)
CreateSuppressionRequest
A suppression to add by hand.
- object
-
emailstring · emailrequiredThe address; any case and surrounding whitespace are normalized.
example
ann@example.com -
scopestringrequiredproject(every list) orlist:<list_id>(one list of this project).example
project -
reasonstring | nullmanual, the only reason a client gives (the default).example
manual
Used by: add_suppression (request)
CreateTemplateRequest
A new template: its version 1.
- object
-
html_bodystringrequiredThe HTML body: 1 byte to 1 MiB. Values are HTML-escaped. A message’s must show
{{ unsubscribe_url }}, itself or through the partials it includes, when the project’sauto_footeris false.example
<p>Hi!</p><a href="{{ unsubscribe_url }}">Unsubscribe</a> -
namestringrequiredUnique in the project: 1 to 128 characters, trimmed.
example
Welcome -
kindTemplateKind | nullmessage(the default) orpartial: a fragment without a subject that other templates include as{% include "name" %}.- message
- partial
-
subjectstring | nullThe subject, a template too: 1 to 998 characters, one line. A message needs one; a partial has none.
example
Welcome, {{ subscriber.attributes.first_name|default('friend') }} -
text_bodystring | nullThe text body: 1 byte to 1 MiB;
nullor left out: made from the HTML when the message is sent.
Used by: create_template (request)
CreatedApiKey
A key just created: the key, and its key string, shown this once.
- object · all fields required
-
created_atstring · date-time -
expires_atstring · date-time | null -
idstring · uuid -
keystring | nullThe key string to send as
Authorization: Bearer. It is not stored and no other answer shows it: keep it now.nullin a replay (Idempotent-Replayed: true) of a request sent again with the sameIdempotency-Key: the key was created by the first request, whose answer carried its string; revoke it and create another with a newIdempotency-Keyif that answer was lost.example
pw_prj_1a2b3c4d_... -
kindApiKeyKindThe kind of an API key.
- admin
- project
-
last_used_atstring · date-time | null -
namestring -
prefixstring -
project_idstring · uuid | null -
revoked_atstring · date-time | null -
scopesarray of Scope
Used by: create_admin_key (201), create_api_key (201)
DnsApplyOutcome
What apply did to one record.
string · enum
- created
- updated
- unchanged
- skipped_exists
- manual
- conflict
- provider_error
- unavailable
DnsCredentials
Which DNS providers the project set its own credentials for; the credentials are never returned.
- object · all fields required
-
porkbunbooleanWhether the project set its own Porkbun credentials.
DnsCredentialsInput
DNS-provider credentials to set.
- object
-
porkbunPorkbunCredentialsBody | nullPorkbun credentials; set them,
nullclears them, absent keeps them. They override the node’s global[dns.porkbun].
DnsProvider
Who applies a domain’s DNS records.
string · enum
- porkbun
- manual
DomainCheck
One verification check: which record, how it came out, and the detail.
- object · all fields required
-
detailstring | nullWhat was found instead of what was expected;
nullwhenok. -
namestringspf_bounce,mx_bounce,dkim,dmarc,tracking_cname,tracking_tlsorptr.example
dkim -
statusCheckStatusHow one verification check came out.
- ok
- missing
- mismatch
- warning
DomainStatus
Where a sending domain stands.
string · enum
- pending
- verified
- failed
Event
One event of a subscriber’s history.
- object · all fields required
-
event_idstring · uuid -
list_idstring · uuid | nullThe list the event is about;
nullfor none. -
payloadobjectWhat the event says, by type: plain values (strings, integers, booleans,
null);actor_key_idis the key that acted. -
project_idstring · uuid -
subscriber_idstring · uuid | nullThe subscriber the event is about;
nullfor none. -
tsstring · date-time -
typestringsubscriber.created,subscriber.unsubscribed,subscriber.resubscribed,subscriber.reactivated, …example
subscriber.created
FromOverride
The sender of a list’s own letters.
- object · all fields required
-
from_emailstring · email -
from_namestring | nullnull: the project’ssettings.from_name.
FromOverrideInput
The sender of a list’s own letters.
- object
-
from_emailstring · emailrequiredThe sender address.
example
news@acme.example -
from_namestring | nullThe sender name, 1 to 128 characters, no line breaks;
nullor left out: the project’ssettings.from_name.example
Acme News
ImportSubscribersRequest
A batch of subscribers to add to a list: each record as the body of
add_subscriber.
- object · all fields required
-
subscribersarray of CreateSubscriberRequestThe records, up to 10 000, in order; the response names an invalid one by its index here.
≤ 10000 items
Used by: import_subscribers (request)
InvalidImportRecord
A record the import did not add, with the first problem of its values.
- object · all fields required
-
codestringinvalidorinvalid_type, as inerrorsof a422.example
invalid -
emailstringThe email as the record had it.
-
fieldstringThe record’s field:
email,attributesorattributes.<key>.example
email -
indexintegerThe record’s index in
subscribers, from 0.≥ 0
-
messagestring
IpPool
An IP pool: a named set of outbound addresses.
- object · all fields required
-
address_countinteger≥ 0 · example
1 -
addressesarray of IpPoolAddress | nullThe addresses; shown to an admin key only,
nullfor a project key.see IpPoolAddress
-
namestringexample
default
IpPoolAddress
One outbound address of an IP pool.
- object · all fields required
-
hostnamestringThe
EHLOname; the address’s PTR points to it.example
mx1.example.com -
ipstring | nullThe local address the node sends from;
null: the system route behind NAT.example
203.0.113.10 -
public_ipstring | nullThe public address behind NAT;
nullwhen there is no NAT.
Language
The language of the public pages.
string · enum
- en
- ru
List
A mailing list of a project.
- object · all fields required
-
confirmation_template_idstring · uuid | nullThe template of the confirmation letter;
null: none. -
created_atstring · date-time -
deleted_atstring · date-time | nullWhen the list was deleted;
nullwhile it is live. A deleted list can only be read. -
double_opt_inbooleanSubscribers confirm by a link before they get campaigns.
-
from_overrideFromOverride | nullThe sender of the list’s own letters;
null: the project’s.see FromOverride
-
idstring · uuidexample
01900000-0000-7000-8000-000000000001 -
namestringexample
Weekly news -
project_idstring · uuidThe list’s project.
-
updated_atstring · date-timeThe latest change: creation, name, options, deletion.
Used by: create_list (201), get_list (200), update_list (200)
ListList
One page of lists.
- object · all fields required
-
itemsarray of ListIn creation order.
see List
-
next_cursorstring | nullPass as
cursorfor the next page;nullon the last page.
Used by: list_lists (200)
PorkbunCredentialsBody
Porkbun API credentials to set.
- object · all fields required
-
api_keystring -
secret_api_keystring
PreviewPart
The part of a message a warning is about.
string · enum
- subject
- html
- text
PreviewTemplateRequest
Whose data a preview renders with: a subscriber of the project, sample attributes, or (neither) the sample context of the check at saving.
- object
-
sample_attributesobject | nullAttributes to render with, as a subscriber’s: string, number or boolean values, up to 64 keys, up to 4 KB of JSON; any other attribute the template names is undefined. Not with
subscriber_id;nullor left out: none. -
subscriber_idstring · uuid | nullA subscriber of the project: its email, attributes and list name. Not with
sample_attributes;nullor left out: none.
Used by: preview_template (request)
PreviewWarning
Something about the preview to look at.
- object · all fields required
-
codestringsubscriber_not_active,subscriber_list_deleted,empty_subject,html_too_large,auto_footer_added,text_from_html.example
auto_footer_added -
messagestring -
partPreviewPart | nullThe part it is about;
null: the message as a whole.- subject
- html
- text
Problem
An error response (RFC 9457 problem details).
- object
-
codestringrequiredThe error code, stable; the table is in
docs/spec/07-api.md.example
key_invalid -
detailstringrequiredWhat went wrong this time, for people.
example
the API key is not valid -
statusinteger · int32requiredThe HTTP status code.
≥ 0 · example
401 -
titlestringrequiredA short summary, the same for every occurrence of the code.
example
API key invalid -
typestringrequiredhttps://postwind.dev/errors/<code>.example
https://postwind.dev/errors/key_invalid -
errorsarray of ProblemFieldErrorEvery invalid field or unmet precondition (
422only); left out otherwise.
Used by: get_server_info (401, 429, 504), whoami (401, 429, 504), list_projects (401, 403, 422, 429, 504), create_project (400, 401, 403, 409, 413, 415, 422, 429, 504), get_project (401, 403, 404, 429, 504), update_project_settings (400, 401, 403, 404, 409, 413, 415, 422, 429, 504), delete_project (401, 403, 404, 429, 504), list_admin_keys (401, 403, 422, 429, 504), create_admin_key (400, 401, 403, 409, 413, 415, 422, 429, 504), revoke_admin_key (401, 403, 404, 409, 429, 504), list_api_keys (401, 403, 404, 422, 429, 504), create_api_key (400, 401, 403, 404, 409, 413, 415, 422, 429, 504), revoke_api_key (401, 403, 404, 409, 429, 504), list_lists (401, 403, 404, 422, 429, 504), create_list (400, 401, 403, 404, 409, 413, 415, 422, 429, 504), get_list (401, 403, 404, 429, 504), update_list (400, 401, 403, 404, 409, 413, 415, 422, 429, 504), delete_list (401, 403, 404, 409, 429, 504), list_subscribers (401, 403, 404, 422, 429, 504), add_subscriber (400, 401, 403, 404, 409, 413, 415, 422, 429, 504), find_subscriber (401, 403, 404, 429, 504), import_subscribers (400, 401, 403, 404, 409, 413, 415, 422, 429, 504), get_subscriber (401, 403, 404, 429, 504), update_subscriber_attributes (400, 401, 403, 404, 409, 413, 415, 422, 429, 504), erase_subscriber (401, 403, 404, 409, 429, 504), get_subscriber_events (401, 403, 404, 422, 429, 504), reactivate_subscriber (400, 401, 403, 404, 409, 413, 415, 422, 429, 504), resubscribe_subscriber (400, 401, 403, 404, 409, 413, 415, 422, 429, 504), unsubscribe_subscriber (400, 401, 403, 404, 409, 413, 415, 422, 429, 504), list_suppressions (401, 403, 404, 422, 429, 504), add_suppression (400, 401, 403, 404, 409, 413, 415, 422, 429, 504), remove_suppression (401, 403, 404, 409, 422, 429, 504), list_sending_domains (401, 403, 404, 422, 429, 504), add_sending_domain (400, 401, 403, 404, 409, 413, 415, 422, 429, 504), get_sending_domain (401, 403, 404, 429, 504), update_sending_domain (400, 401, 403, 404, 422, 429, 504), delete_sending_domain (401, 403, 404, 409, 429, 504), apply_dns_records (401, 403, 404, 409, 422, 429, 504), get_required_dns_records (401, 403, 404, 422, 429, 504), verify_sending_domain (401, 403, 404, 409, 422, 429, 504), list_templates (401, 403, 404, 422, 429, 504), create_template (400, 401, 403, 404, 409, 413, 415, 422, 429, 504), get_template (401, 403, 404, 429, 504), update_template (400, 401, 403, 404, 409, 413, 415, 422, 429, 504), preview_template (400, 401, 403, 404, 409, 413, 415, 422, 429, 504), send_test_email (400, 401, 403, 404, 409, 413, 415, 422, 429, 504), get_template_version (401, 403, 404, 429, 504), list_campaigns (401, 403, 404, 422, 429, 504), create_campaign (400, 401, 403, 404, 409, 413, 415, 422, 429, 504), get_campaign (401, 403, 404, 429, 504), update_campaign (400, 401, 403, 404, 409, 413, 415, 422, 429, 504), cancel_campaign (401, 403, 404, 409, 422, 429, 504), launch_campaign (401, 403, 404, 409, 422, 429, 504), pause_campaign (401, 403, 404, 409, 422, 429, 504), preflight_campaign (401, 403, 404, 409, 422, 429, 504), resume_campaign (401, 403, 404, 409, 422, 429, 504), get_campaign_stats (401, 403, 404, 429, 504)
ProblemFieldError
One invalid field or unmet precondition.
- object · all fields required
-
codestringWhat is wrong with it,
snake_case.example
invalid -
fieldstringThe field, as named in the request.
example
name -
messagestringexample
must not be empty
Project
A project.
- object · all fields required
-
created_atstring · date-time -
deleted_atstring · date-time | nullWhen the project was deleted;
nullwhile it is live. A deleted project can only be read. -
idstring · uuidexample
01900000-0000-7000-8000-000000000001 -
namestringexample
Acme News -
settingsProjectSettingsA project’s settings, every field present.
see ProjectSettings
-
slugstringexample
acme-news -
updated_atstring · date-timeThe latest change: creation, rename, settings, deletion.
Used by: create_project (201), get_project (200), update_project_settings (200)
ProjectList
One page of projects.
- object · all fields required
-
itemsarray of ProjectIn creation order.
see Project
-
next_cursorstring | nullPass as
cursorfor the next page;nullon the last page.
Used by: list_projects (200)
ProjectSettings
A project’s settings, every field present.
- object · all fields required
-
auto_footerbooleanAdd an unsubscribe footer when a template has none.
-
brandingBrandingHow the public pages look.
see Branding
-
daily_send_quotainteger · int32 | nullMost messages a day;
null: no quota.≥ 0
-
default_throttle_per_hourinteger · int32 | nullDefault campaign speed, messages an hour;
null: no limit.≥ 0
-
dns_credentialsDnsCredentialsWhich DNS providers the project set its own credentials for; the credentials are never returned.
see DnsCredentials
-
from_emailstring · email | nullDefault sender address of campaigns.
-
from_namestring | nullDefault sender name of campaigns.
-
reply_tostring · email | nullDefault
Reply-To. -
soft_bounce_suppress_afterinteger · int32 | nullSoft bounces in a row after which an address is suppressed;
null: off.≥ 0
-
trackingTrackingWhat campaigns track by default.
see Tracking
-
transportstring | nullDefault transport,
directorrelay:<name>;null: the node’sdelivery.default_transport.
ProjectSettingsInput
Project settings to set: a field left out keeps its value (the default
for a new project), null clears a field that may be empty.
- object
-
auto_footerbooleanAdd an unsubscribe footer when a template has none.
-
brandingBrandingInputBranding of the public pages to set.
see BrandingInput
-
daily_send_quotainteger · int64 | nullMost messages a day, 1 or more;
null: no quota.1–4294967295
-
default_throttle_per_hourinteger · int64 | nullDefault campaign speed, messages an hour;
null: no limit.1–4294967295
-
dns_credentialsDnsCredentialsInputDNS-provider credentials of the project. Write-only: a read never returns them.
-
from_emailstring · email | nullDefault sender address of campaigns.
example
news@acme.example -
from_namestring | nullDefault sender name of campaigns, 1 to 128 characters, no line breaks.
example
Acme News -
reply_tostring · email | nullDefault
Reply-To. -
soft_bounce_suppress_afterinteger · int64 | nullSoft bounces in a row after which an address is suppressed;
null: off.1–4294967295
-
trackingTrackingInputTracking defaults to set.
see TrackingInput
-
transportstring | nullDefault transport:
directorrelay:<name>of a relay the node offers (GET /api/v1/server);null: the node’s default.example
direct
ReactivateRequest
Why a bounced or complained subscriber may get mail again.
- object · all fields required
-
reasonstring1 to 256 characters. Recorded in the event
subscriber.reactivated.example
the mailbox works again (ticket 4711)
Used by: reactivate_subscriber (request)
RecordPurpose
What a required record is for.
string · enum
- spf_bounce
- mx_bounce
- dkim
- dmarc
- tracking_cname
RecordType
The type of a DNS record.
string · enum
- txt
- mx
- cname
RejectStage
The session stage a refusal happened at.
string · enum
- connect
- rcpt
- data
RequiredDnsRecords
The records a sending domain needs.
- object · all fields required
-
required_recordsarray of RequiredRecordWhat to create in DNS, in this order.
see RequiredRecord
Used by: get_required_dns_records (200)
RequiredRecord
A DNS record a sending domain needs.
- object · all fields required
-
contentstringThe whole value; a TXT value over 255 characters is split into strings by the DNS provider, not here.
example
v=spf1 ip4:203.0.113.10 -all -
create_only_if_absentbooleanCreate it only if the name has no record of this type, and never change one that is there (the DMARC record).
-
namestringThe owner name, without a trailing dot.
example
bounce.news.example.com -
priorityinteger · int32 | nullThe MX priority;
nullfor other types.≥ 0 · example
10 -
purposeRecordPurposeWhat a required record is for.
- spf_bounce
- mx_bounce
- dkim
- dmarc
- tracking_cname
-
typeRecordTypeThe type of a DNS record.
- txt
- mx
- cname
ResubscribeRequest
The new consent of a resubscribe.
- object · all fields required
-
consent_sourcestringWhere the new consent came from (a form, a support ticket); 1 to 256 characters. Recorded in the event
subscriber.resubscribed.example
signup form, 2026-11-07
Used by: resubscribe_subscriber (request)
Scope
A right of a project key. An admin key has all of them.
string · enum
- read
- write
- send
- keys
SendingDomain
A sending domain. Its DKIM private key is in no answer.
- object · all fields required
-
bounce_subdomainstringexample
bounce.news.example.com -
checksarray of DomainCheckOne entry per check that ran, in the canonical order; empty until the domain is first verified.
see DomainCheck
-
created_atstring · date-time -
dkim_public_keystringThe DKIM public key: base64 of its DER
SubjectPublicKeyInfo, thep=of the DKIM record (RSA 2048). -
dkim_selectorstringexample
pw1 -
dns_providerDnsProviderWho applies a domain’s DNS records.
- porkbun
- manual
-
domainstringIn punycode for an international name.
example
news.example.com -
idstring · uuidexample
01900000-0000-7000-8000-000000000001 -
ip_poolstringexample
default -
last_checked_atstring · date-time | nullWhen the records were last checked (RFC 3339);
nulluntil then. -
project_idstring · uuid -
statusDomainStatusWhere a sending domain stands.
- pending
- verified
- failed
-
tracking_hoststring | nullnull: none. -
updated_atstring · date-time
Used by: get_sending_domain (200), verify_sending_domain (200)
SendingDomainList
One page of sending domains.
- object · all fields required
-
itemsarray of SendingDomainIn creation order.
see SendingDomain
-
next_cursorstring | nullPass as
cursorfor the next page;nullon the last page.
Used by: list_sending_domains (200)
ServerResponse
What the node that answered runs and offers.
- object · all fields required
-
available_transportsarray of stringThe transports this node can send through now; a message whose transport is not here is not sent (
test-sendanswers422transport_unavailable). Empty until the built-indirectandrelaytransports ship.example
[] -
default_transportstringThe transport a project without its own uses.
example
direct -
dns_providersarray of stringDNS providers a sending domain may name:
manualalways,porkbunwhen it is configured.example
["manual","porkbun"] -
enabled_subservicesarray of stringSubservices enabled on this node, in start order:
api,mcp,web,smtp.inbound,delivery.example
["api","mcp","web","smtp.inbound","delivery"] -
ip_poolsarray of IpPoolIP pools by name, for a sending domain’s
ip_pool.see IpPool
-
transportsarray of stringDelivery transports a project may use:
direct(built in) andrelay:<name>for each configured relay.example
["direct","relay:ses"] -
versionstringPostwind version and git commit, as
postwind --versionprints them.example
0.1.0 (abc1234)
Used by: get_server_info (200)
Subscriber
A subscriber of a list.
- object · all fields required
-
attributesobjectThe subscriber’s attributes, a map of string, number or boolean values.
-
confirmed_atstring · date-time | nullWhen the subscriber confirmed a double opt-in;
nullotherwise. -
created_atstring · date-time -
emailstring · emailexample
ann@example.com -
idstring · uuidexample
01900000-0000-7000-8000-000000000001 -
list_idstring · uuidThe list the subscriber is on.
-
project_idstring · uuidThe subscriber’s project.
-
soft_bounce_streakinteger · int32Soft bounces in a row; reset by a delivery (P4+).
≥ 0
-
sourcestringHow the subscriber was added:
api,importorconfirm. -
statusstringpending,active,unsubscribed,bouncedorcomplained.example
active -
unsubscribed_atstring · date-time | nullWhen the subscriber unsubscribed;
nullotherwise. -
updated_atstring · date-timeThe latest change: creation, an attribute merge, a status change.
Used by: add_subscriber (200, 201), find_subscriber (200), get_subscriber (200), update_subscriber_attributes (200), reactivate_subscriber (200), resubscribe_subscriber (200), unsubscribe_subscriber (200)
SubscriberEventList
One page of a subscriber’s events.
- object · all fields required
-
itemsarray of EventOldest first: by time, then by event id.
see Event
-
next_cursorstring | nullPass as
cursorfor the next page;nullon the last page.
Used by: get_subscriber_events (200)
SubscriberImportReport
What an import did, record by record: created + updated + invalid.length is the number of records.
- object · all fields required
-
createdintegerRecords whose address was not on the list: new subscribers.
≥ 0
-
invalidarray of InvalidImportRecordRecords not added, by index.
-
pending_confirmationintegerOf the created subscribers, those
pending(the list has double opt-in).≥ 0
-
updatedintegerValid records whose address was already on the list or came earlier in the batch: merged into that subscriber, its status kept.
≥ 0
Used by: import_subscribers (200)
SubscriberList
One page of subscribers.
- object · all fields required
-
itemsarray of SubscriberOrdered by id.
see Subscriber
-
next_cursorstring | nullPass as
cursorfor the next page;nullon the last page.
Used by: list_subscribers (200)
Suppression
An address on the project’s suppression list: it gets no mail of the scope.
- object · all fields required
-
created_atstring · date-time -
emailstring · emailexample
ann@example.com -
project_idstring · uuidThe suppression’s project.
-
reasonstringunsubscribed_all,unsubscribed_list,hard_bounce,soft_bounce_limit,complaintormanual.example
manual -
scopestringproject(every list) orlist:<list_id>.example
project -
sourcestringWhere it came from:
api(the API or MCP),web,deliveryorinbound.example
api
Used by: add_suppression (200, 201)
SuppressionList
One page of suppressions.
- object · all fields required
-
itemsarray of SuppressionBy address, then by scope.
see Suppression
-
next_cursorstring | nullPass as
cursorfor the next page;nullon the last page.
Used by: list_suppressions (200)
Template
One version of a template.
- object · all fields required
-
created_atstring · date-timeWhen this version was saved.
-
engineTemplateEngineThe template engine.
- minijinja
-
html_bodystring -
idstring · uuidThe template’s id, the same in every version.
example
01900000-0000-7000-8000-000000000001 -
kindTemplateKindWhat a template is.
- message
- partial
-
namestringexample
Welcome -
project_idstring · uuid -
subjectstring | nullnullfor a partial. -
text_bodystring | nullnull: the text is made from the HTML when the message is sent. -
versioninteger · int32From 1, one more at each save.
≥ 1 · example
2
Used by: create_template (201), get_template (200), update_template (200), get_template_version (200)
TemplateEngine
The template engine.
string · enum
- minijinja
TemplateKind
What a template is.
string · enum
- message
- partial
TemplateList
One page of templates.
- object · all fields required
-
itemsarray of TemplateSummaryIn id order, each by its latest version.
see TemplateSummary
-
next_cursorstring | nullPass as
cursorfor the next page;nullon the last page.
Used by: list_templates (200)
TemplatePreview
A message as a subscriber would get it.
- object · all fields required
-
htmlstringThe HTML part, with the automatic footer when it was added.
-
subjectstring -
textstringThe text part: the text body, or the HTML made into text; with the automatic footer when it was added.
-
warningsarray of PreviewWarningsee PreviewWarning
Used by: preview_template (200)
TemplateSummary
A template as a list shows it: its latest version, without sources.
- object · all fields required
-
created_atstring · date-timeWhen the latest version was saved.
-
idstring · uuid -
kindTemplateKindWhat a template is.
- message
- partial
-
namestring -
project_idstring · uuid -
versioninteger · int32The latest version.
≥ 1
TestSend
What a test send did.
- object · all fields required
-
from_emailstringThe sender: the project’s
settings.from_email.example
news@example.com -
resultsarray of TestSendResultOne per distinct address, in the order of the request.
see TestSendResult
-
subjectstringThe subject every message carries:
[TEST]and the rendered one.example
[TEST] Welcome, Ann -
transportstringThe transport the messages went through:
direct,relay:<name>.example
direct
Used by: send_test_email (200)
TestSendOutcome
How the test message to one address went.
string · enum
- accepted
- deferred
- rejected
- suppressed
- failed
TestSendRequest
The addresses a test message goes to, and the data to render it with.
- object
-
toarray of stringrequired1 to 10 addresses; a repeated address (after normalization) gets one message.
example
["me@example.com"] -
sample_attributesobject | nullAttributes to render with, as a subscriber’s: string, number or boolean values, up to 64 keys, up to 4 KB of JSON; any other attribute the template names is undefined.
nullor left out: every attribute is the textsample.
Used by: send_test_email (request)
TestSendResult
The test message to one address.
- object · all fields required
-
emailstringThe address, normalized.
example
me@example.com -
message_idstring | nullThe message’s
Message-ID, without angle brackets;nullwhen it was not sent (suppressed). -
outcomeTestSendOutcomeHow the test message to one address went.
- accepted
- deferred
- rejected
- suppressed
- failed
-
smtp_codeinteger · int32 | nullThe reply code of a refusal (
deferred,rejected); otherwisenull.≥ 0 · example
550 -
smtp_textstring | nullThe reply text of a refusal (
deferred,rejected); otherwisenull. -
stageRejectStage | nullThe stage of a
rejected; otherwisenull.- connect
- rcpt
- data
Tracking
What campaigns track by default.
- object · all fields required
-
clicksboolean -
opensboolean
TrackingInput
Tracking defaults to set.
- object
-
clicksbooleanClick redirects.
-
opensbooleanOpen pixel.
TrackingOverride
What a campaign tracks.
- object · all fields required
-
clicksboolean -
opensboolean
TrackingOverrideInput
What a campaign tracks in place of the project’s settings.tracking.
- object · all fields required
-
clicksbooleanClick redirects.
-
opensbooleanThe open pixel.
UnsubscribeRequest
From what to unsubscribe.
- object
-
scopestring | nulllist(default): from the subscriber’s list;project: from every list of the project.example
list
Used by: unsubscribe_subscriber (request)
UpdateCampaignRequest
A partial update (JSON merge patch): a field left out keeps its value,
null clears a field that may be empty. list_ids and
tracking_override are replaced as a whole. Only a draft or
scheduled campaign takes a change.
- object
-
from_emailstring · email | null -
from_namestring | null -
list_idsarray of string1 to 16 distinct ids of live lists of the project.
1–16 items
-
namestringexample
Spring sale, final -
reply_tostring · email | null -
subject_overridestring | null -
template_idstring · uuidA message template of the project.
-
throttle_per_hourinteger · int64 | null1–4294967295
-
tracking_overrideTrackingOverrideInput | nullWhat a campaign tracks in place of the project’s
settings.tracking. -
transport_overridestring | null
Used by: update_campaign (request)
UpdateListRequest
A partial update (JSON merge patch): a field left out keeps its value,
null clears a field that may be empty. from_override is replaced as
a whole.
- object
-
confirmation_template_idstring · uuid | nullThe template of the confirmation letter, a message template of the project;
nullclears it (not whiledouble_opt_inis on). -
double_opt_inbooleanTurn double opt-in on (needs a
confirmation_template_id, the list’s or this one) or off. -
from_overrideFromOverrideInput | nullThe sender of the list’s own letters, replaced as a whole;
null: the project’s. -
namestringThe new name.
example
Monthly news
Used by: update_list (request)
UpdateProjectRequest
A partial update (JSON merge patch): a field left out keeps its value,
null clears a field that may be empty.
- object
-
namestringThe new name.
example
Acme Inc -
settingsProjectSettingsInputSettings to change; the rest keep their values.
Used by: update_project_settings (request)
UpdateSendingDomainRequest
A change to a sending domain. Every field is optional: left out keeps
its value; null clears a tracking_host (the others refuse null).
- object
-
Who applies the records:
porkbunormanual.- porkbun
- manual
-
ip_poolstringThe IP pool to send from (
GET /api/v1/serverlists them). Changing it moves the domain topending.example
default -
tracking_hoststring | nullA host for tracking and unsubscribe links;
nullclears it. Changing it moves the domain topending.example
links.example.com
Used by: update_sending_domain (request)
UpdateSubscriberRequest
A change to a subscriber’s attributes (JSON merge patch): a key sets or
(with null) removes that attribute; keys left out are kept.
- object · all fields required
-
attributesobjectAttributes to set or remove (
null).
Used by: update_subscriber_attributes (request)
UpdateTemplateRequest
The sources of a template’s new version. The name and the kind stay.
- object
-
html_bodystringrequiredThe HTML body, as at creation.
-
subjectstring | nullThe subject, as at creation.
-
text_bodystring | nullThe text body;
nullor left out: made from the HTML.
Used by: update_template (request)
UpdatedSendingDomain
A sending domain after a change, and, when the change moved it back to
pending, the records it now needs.
- object · extends SendingDomain · all fields required
-
bounce_subdomainstringexample
bounce.news.example.com -
checksarray of DomainCheckOne entry per check that ran, in the canonical order; empty until the domain is first verified.
see DomainCheck
-
created_atstring · date-time -
dkim_public_keystringThe DKIM public key: base64 of its DER
SubjectPublicKeyInfo, thep=of the DKIM record (RSA 2048). -
dkim_selectorstringexample
pw1 -
dns_providerDnsProviderWho applies a domain’s DNS records.
- porkbun
- manual
-
domainstringIn punycode for an international name.
example
news.example.com -
idstring · uuidexample
01900000-0000-7000-8000-000000000001 -
ip_poolstringexample
default -
last_checked_atstring · date-time | nullWhen the records were last checked (RFC 3339);
nulluntil then. -
project_idstring · uuid -
required_recordsarray of RequiredRecord | nullThe records to create after an
ip_poolortracking_hostchange;nullwhen the change left the domain verified or failed.see RequiredRecord
-
statusDomainStatusWhere a sending domain stands.
- pending
- verified
- failed
-
tracking_hoststring | nullnull: none. -
updated_atstring · date-time
Used by: update_sending_domain (200)
WhoamiResponse
The key the request was made with.
- object · all fields required
-
expires_atstring · date-time | nullWhen the key stops working;
null: never. -
key_idstring · uuidThe key’s id: what revoking it takes.
example
01900000-0000-7000-8000-000000000001 -
kindApiKeyKindThe kind of an API key.
- admin
- project
-
namestringThe name its owner gave it.
example
ops -
project_idstring · uuid | nullThe key’s project;
nullfor an admin key. -
scopesarray of ScopeWhat the key may do. An admin key has every scope, and may manage projects and admin keys besides.
Used by: whoami (200)