Palisade API
Version 2025-04-30 · OpenAPI JSON · Guide
The Palisade API uses independent rate-limit buckets. Honor the response headers — do not hard-code limits.
Buckets
- Global — applies to every request reaching the API (public and authenticated alike).
- DNS — applies in addition to the global bucket on endpoints that trigger outbound DNS resolution during the request (domain verify, find-dkim-keys, the DNS-reading tools — audit, mailbox provider, SPF include validation, DNS lookup and header analysis — and DNS provider detect). A request can hit either bucket independently.
- API key — applies in addition to the global bucket on every request authenticated with an API key. Each key gets its own bucket, shared across all API instances.
- API key DNS — a stricter per-key bucket that applies in addition to the DNS bucket on the same DNS-triggering endpoints when the request is authenticated with an API key.
- Signup — a per-IP bucket on the headless signup endpoint.
- MCP OAuth — a per-subject bucket on the MCP server for requests authenticated with an OAuth (JWT) token, mirroring the API-key bucket for token callers.
Headers on every response
RateLimit-Limit,RateLimit-Remaining,RateLimit-Reset— current bucket state.
Headers on 429 responses
Retry-After— seconds to wait before retrying.
429 response body
{ "error": "rate_limit_exceeded", "scope": "global" | "dns" | "api_key" | "api_key_dns" | "signup" | "mcp_oauth", "limit": N, "window_seconds": N, "retry_after_seconds": N, "message": "..." }. Clients must respect Retry-After and back off exponentially on repeat failures.
Keying
Limits are applied per API key when the request carries Basic credentials, per JWT subject for dashboard-session callers, and fall back to per source IP otherwise. Multiple keys from the same host each get their own bucket.
Authentication
Authenticated endpoints accept either scheme below. API-key clients must also send the Palisade-Version header on every request.
API key sent as HTTP Basic credentials. Put the API key in the username and leave the password empty: Authorization: Basic base64(<api_key>:).
Health Check
Check API availability
/health-checkExample request
curl "https://api.palisade.email/health-check"
Responses
Success
Response body
Domain
List domains
/domainsrequires authQuery parameters
true, falsenone, quarantine, rejectdrifted, none, pending, setup, failedtrue, false"severity" orders by ticket priority, then count, with no-ticket domains last under desc and first under asc. "status" keeps configured domains (including zero tickets) before monitoring/setup states in both directions, and applies severity ordering within each group.
created_at, url, monitoring_status, dmarc_policy, score, last_14_days_volume, last_14_days_dmarc_pass_pct, last_14_days_spf_pass_pct, last_14_days_dkim_pass_pct, open_tasks_count, severity, status, groupdesc, ascgroup, tasksHeaders
2025-04-30, unstableExample request
curl "https://api.palisade.email/domains" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
Domain
properties
none, quarantine, reject0 · Max: 100none, quarantine, reject, sameproperties
properties
unknown, syncing, ready, errorunknown, syncing, ready, errorunknown, syncing, ready, errorunknown, syncing, ready, errorunknown, syncing, ready, errorWhen each managed record last entered the "syncing" status. For dmarc, falls back to dmarc_setup_at when the transition predates tracking; other records are null when they have never synced or the transition predates tracking. Useful for estimating how long a "syncing" record has been waiting on DNS propagation.
properties
drifted, none, pending, setup, failednameservers_unresolvable, dmarc_record_missing, dmarc_record_added_as_txt_not_cname, dmarc_record_on_parent_only, dmarc_record_missing_palisade_rua, dmarc_record_invalid, dmarc_multiple_recordsDmarcSetupFailureDetail
Open tickets on this domain. Opportunity tickets such as set_up_bimi are not counted, and expand[]=tasks leaves them out to match.
0Priority of the most urgent open task on this domain, on the same inverted scale as a task's own priority: 0 critical, 1 high, 2 medium, 3 low. Null when the domain has no open tasks. Sort on "severity" to order domains by it.
0 · Max: 30 · Max: 100Risk band the score falls in: critical, bad, good, or great. The same banding the dashboard shows, so clients do not have to reimplement the thresholds.
critical, bad, good, greatproperties
Why managed_dns_status.bimi is "error". "setup_timeout" means the customer CNAME was never detected within the verification window (setup was never completed); "drift" means a previously verified CNAME stopped pointing at Palisade; "record_conflict" means default._bimi holds conflicting records — see dns_conflicts. Null when there is no error or the error predates reason tracking.
setup_timeout, drift, certificate_invalid, record_conflict, delegation_missing, publish_failed, dkim_key_error, check_failedWhy managed_dns_status.bimi is "error". "setup_timeout" means the customer CNAME was never detected within the verification window (setup was never completed); "drift" means a previously verified CNAME stopped pointing at Palisade; "record_conflict" means default._bimi holds conflicting records — see dns_conflicts. Null when there is no error or the error predates reason tracking.
Why managed_dns_status.bimi is "error". "setup_timeout" means the customer CNAME was never detected within the verification window (setup was never completed); "drift" means a previously verified CNAME stopped pointing at Palisade; "record_conflict" means default._bimi holds conflicting records — see dns_conflicts. Null when there is no error or the error predates reason tracking.
Why managed_dns_status.bimi is "error". "setup_timeout" means the customer CNAME was never detected within the verification window (setup was never completed); "drift" means a previously verified CNAME stopped pointing at Palisade; "record_conflict" means default._bimi holds conflicting records — see dns_conflicts. Null when there is no error or the error predates reason tracking.
Why managed_dns_status.bimi is "error". "setup_timeout" means the customer CNAME was never detected within the verification window (setup was never completed); "drift" means a previously verified CNAME stopped pointing at Palisade; "record_conflict" means default._bimi holds conflicting records — see dns_conflicts. Null when there is no error or the error predates reason tracking.
Unresolved record conflicts observed at labels Palisade manages or monitors for this domain. Empty for a healthy domain. Each entry quotes the offending records verbatim along with what every authoritative nameserver and public resolver returned, so it can be acted on without a second investigation.
DnsConflict
The exact DNS name the conflicting records sit at.
dmarc, spf, bimi, mta_sts, dkimcname_with_other_data, multiple_dmarc_records, multiple_spf_records, multiple_bimi_records, cname_target_unresolvable, cname_chain_too_deep, authoritative_disagreement, resolver_divergence, managed_delegation_missingThe specification clause the zone violates, e.g. "RFC 1034 §3.6.2".
What this actually does to mail for this domain, in plain language.
Which record to delete and which to keep, stated concretely enough to act on.
The offending record values, verbatim as published.
Every authoritative nameserver queried and exactly what it returned.
items
Independent public resolvers queried and exactly what each returned.
items
How many detection runs have observed this conflict.
The host a customer CNAMEs default._bimi.{domain} to for Palisade-served BIMI.
The fully-formed BIMI TXT value, populated whenever bimi_options.logo is set (via asset ingestion or a direct bimi_options update). The a= tag is included only when a certificate URL is also set. Customers who prefer not to delegate via CNAME can publish this value at default._bimi.{domain} themselves.
00 · Max: 1000 · Max: 1000 · Max: 100Group
properties
Returns only tasks with status "open"
Task
properties
The domain audit score as it stands now.
0 · Max: 100How much of the domain score completing this ticket wins back, by the same scoring the domain overview shows. 0 for ticket types the score does not measure. Present only with expand[]=domain, since it depends on the domain as it stands now.
0properties
properties
SENDING_TOOL, MAILBOX_PROVIDER, VPS_PROVIDER, SECURITY_PROVIDER, EMAIL_RELAYNOT_FORWARDER, FORWARDER, FORWARDER_ONLYNONE, RARE, FULLitems
DIRECT, SUBDOMAIN, MANAGED_SUBDOMAINproperties
properties
properties
NONE, RARE, FULLBETA: Only expandable for GET /tasks/:id. Can contain instructions sometimes.
properties
items
TXT, CNAMEWhere the task sits in the email-authentication rollout, lower first: 10 DMARC setup, 20 foundation records, 30 SPF/DKIM alignment, 40 cleanup, 50 enforcement, 60 hardening. Separate from priority, which is urgency; sequence orders tasks of equal priority, since an alignment task cannot be worked before DMARC reporting exists to show the failure.
open, snoozed, canceled, dismissed, pending, donecleanup_spf_record, confirm_source, lockdown_domain, reduce_spf_lookups, set_up_dmarc_record, source_failing_dkim, source_failing_spf, set_up_mx_record, set_up_spf_record, update_dmarc_record, update_ttl, set_up_mta_sts, set_up_tls_rpt, resolve_dns_conflict, review_unused_sender, cleanup_sender_records, fix_mx_certificate, renew_vmc_certificate, dkim_selector_not_imported, set_up_bimiWhy a done ticket closed. 'verified': Palisade's own check found the problem gone. 'manual': a person or an API caller marked it done and nothing was checked. Null on a ticket that is not done, and on one closed before the reason was first recorded. More values may be added, so treat an unknown one as unspecified.
verified, manualWhen the domain first reached the "setup" monitoring status and DMARC report collection began.
The first day (yyyy-MM-dd) a DMARC aggregate report was actually received for this domain. The honest denominator for any activity claim: nothing before this day was observable, so a domain monitored for a week can never truthfully read as quiet for ninety days. Null until the first report arrives.
properties
Add a domain
/domainsrequires authHeaders
2025-04-30, unstableRequest body
Example request
curl -X POST "https://api.palisade.email/domains" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30" \
-H "Content-Type: application/json" \
-d '{
"url": "string",
"group_id": "5cf10a30-0b0c-4e05-9e68-6cbfd7d3c2a1",
"use_stored_scan": true
}'
Responses
Success
Response body
properties
none, quarantine, reject0 · Max: 100none, quarantine, reject, sameproperties
properties
unknown, syncing, ready, errorunknown, syncing, ready, errorunknown, syncing, ready, errorunknown, syncing, ready, errorunknown, syncing, ready, errorWhen each managed record last entered the "syncing" status. For dmarc, falls back to dmarc_setup_at when the transition predates tracking; other records are null when they have never synced or the transition predates tracking. Useful for estimating how long a "syncing" record has been waiting on DNS propagation.
properties
drifted, none, pending, setup, failednameservers_unresolvable, dmarc_record_missing, dmarc_record_added_as_txt_not_cname, dmarc_record_on_parent_only, dmarc_record_missing_palisade_rua, dmarc_record_invalid, dmarc_multiple_recordsDmarcSetupFailureDetail
Open tickets on this domain. Opportunity tickets such as set_up_bimi are not counted, and expand[]=tasks leaves them out to match.
0Priority of the most urgent open task on this domain, on the same inverted scale as a task's own priority: 0 critical, 1 high, 2 medium, 3 low. Null when the domain has no open tasks. Sort on "severity" to order domains by it.
0 · Max: 30 · Max: 100Risk band the score falls in: critical, bad, good, or great. The same banding the dashboard shows, so clients do not have to reimplement the thresholds.
critical, bad, good, greatproperties
Why managed_dns_status.bimi is "error". "setup_timeout" means the customer CNAME was never detected within the verification window (setup was never completed); "drift" means a previously verified CNAME stopped pointing at Palisade; "record_conflict" means default._bimi holds conflicting records — see dns_conflicts. Null when there is no error or the error predates reason tracking.
setup_timeout, drift, certificate_invalid, record_conflict, delegation_missing, publish_failed, dkim_key_error, check_failedWhy managed_dns_status.bimi is "error". "setup_timeout" means the customer CNAME was never detected within the verification window (setup was never completed); "drift" means a previously verified CNAME stopped pointing at Palisade; "record_conflict" means default._bimi holds conflicting records — see dns_conflicts. Null when there is no error or the error predates reason tracking.
Why managed_dns_status.bimi is "error". "setup_timeout" means the customer CNAME was never detected within the verification window (setup was never completed); "drift" means a previously verified CNAME stopped pointing at Palisade; "record_conflict" means default._bimi holds conflicting records — see dns_conflicts. Null when there is no error or the error predates reason tracking.
Why managed_dns_status.bimi is "error". "setup_timeout" means the customer CNAME was never detected within the verification window (setup was never completed); "drift" means a previously verified CNAME stopped pointing at Palisade; "record_conflict" means default._bimi holds conflicting records — see dns_conflicts. Null when there is no error or the error predates reason tracking.
Why managed_dns_status.bimi is "error". "setup_timeout" means the customer CNAME was never detected within the verification window (setup was never completed); "drift" means a previously verified CNAME stopped pointing at Palisade; "record_conflict" means default._bimi holds conflicting records — see dns_conflicts. Null when there is no error or the error predates reason tracking.
Unresolved record conflicts observed at labels Palisade manages or monitors for this domain. Empty for a healthy domain. Each entry quotes the offending records verbatim along with what every authoritative nameserver and public resolver returned, so it can be acted on without a second investigation.
DnsConflict
The exact DNS name the conflicting records sit at.
dmarc, spf, bimi, mta_sts, dkimcname_with_other_data, multiple_dmarc_records, multiple_spf_records, multiple_bimi_records, cname_target_unresolvable, cname_chain_too_deep, authoritative_disagreement, resolver_divergence, managed_delegation_missingThe specification clause the zone violates, e.g. "RFC 1034 §3.6.2".
What this actually does to mail for this domain, in plain language.
Which record to delete and which to keep, stated concretely enough to act on.
The offending record values, verbatim as published.
Every authoritative nameserver queried and exactly what it returned.
items
Independent public resolvers queried and exactly what each returned.
items
How many detection runs have observed this conflict.
The host a customer CNAMEs default._bimi.{domain} to for Palisade-served BIMI.
The fully-formed BIMI TXT value, populated whenever bimi_options.logo is set (via asset ingestion or a direct bimi_options update). The a= tag is included only when a certificate URL is also set. Customers who prefer not to delegate via CNAME can publish this value at default._bimi.{domain} themselves.
00 · Max: 1000 · Max: 1000 · Max: 100When the domain first reached the "setup" monitoring status and DMARC report collection began.
The first day (yyyy-MM-dd) a DMARC aggregate report was actually received for this domain. The honest denominator for any activity claim: nothing before this day was observable, so a domain monitored for a week can never truthfully read as quiet for ninety days. Null until the first report arrives.
Conflict
Response body
Get a domain
/domains/{id}requires authPath parameters
Headers
2025-04-30, unstableExample request
curl "https://api.palisade.email/domains/<id>" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
properties
none, quarantine, reject0 · Max: 100none, quarantine, reject, sameproperties
properties
unknown, syncing, ready, errorunknown, syncing, ready, errorunknown, syncing, ready, errorunknown, syncing, ready, errorunknown, syncing, ready, errorWhen each managed record last entered the "syncing" status. For dmarc, falls back to dmarc_setup_at when the transition predates tracking; other records are null when they have never synced or the transition predates tracking. Useful for estimating how long a "syncing" record has been waiting on DNS propagation.
properties
drifted, none, pending, setup, failednameservers_unresolvable, dmarc_record_missing, dmarc_record_added_as_txt_not_cname, dmarc_record_on_parent_only, dmarc_record_missing_palisade_rua, dmarc_record_invalid, dmarc_multiple_recordsDmarcSetupFailureDetail
Open tickets on this domain. Opportunity tickets such as set_up_bimi are not counted, and expand[]=tasks leaves them out to match.
0Priority of the most urgent open task on this domain, on the same inverted scale as a task's own priority: 0 critical, 1 high, 2 medium, 3 low. Null when the domain has no open tasks. Sort on "severity" to order domains by it.
0 · Max: 30 · Max: 100Risk band the score falls in: critical, bad, good, or great. The same banding the dashboard shows, so clients do not have to reimplement the thresholds.
critical, bad, good, greatproperties
Why managed_dns_status.bimi is "error". "setup_timeout" means the customer CNAME was never detected within the verification window (setup was never completed); "drift" means a previously verified CNAME stopped pointing at Palisade; "record_conflict" means default._bimi holds conflicting records — see dns_conflicts. Null when there is no error or the error predates reason tracking.
setup_timeout, drift, certificate_invalid, record_conflict, delegation_missing, publish_failed, dkim_key_error, check_failedWhy managed_dns_status.bimi is "error". "setup_timeout" means the customer CNAME was never detected within the verification window (setup was never completed); "drift" means a previously verified CNAME stopped pointing at Palisade; "record_conflict" means default._bimi holds conflicting records — see dns_conflicts. Null when there is no error or the error predates reason tracking.
Why managed_dns_status.bimi is "error". "setup_timeout" means the customer CNAME was never detected within the verification window (setup was never completed); "drift" means a previously verified CNAME stopped pointing at Palisade; "record_conflict" means default._bimi holds conflicting records — see dns_conflicts. Null when there is no error or the error predates reason tracking.
Why managed_dns_status.bimi is "error". "setup_timeout" means the customer CNAME was never detected within the verification window (setup was never completed); "drift" means a previously verified CNAME stopped pointing at Palisade; "record_conflict" means default._bimi holds conflicting records — see dns_conflicts. Null when there is no error or the error predates reason tracking.
Why managed_dns_status.bimi is "error". "setup_timeout" means the customer CNAME was never detected within the verification window (setup was never completed); "drift" means a previously verified CNAME stopped pointing at Palisade; "record_conflict" means default._bimi holds conflicting records — see dns_conflicts. Null when there is no error or the error predates reason tracking.
Unresolved record conflicts observed at labels Palisade manages or monitors for this domain. Empty for a healthy domain. Each entry quotes the offending records verbatim along with what every authoritative nameserver and public resolver returned, so it can be acted on without a second investigation.
DnsConflict
The exact DNS name the conflicting records sit at.
dmarc, spf, bimi, mta_sts, dkimcname_with_other_data, multiple_dmarc_records, multiple_spf_records, multiple_bimi_records, cname_target_unresolvable, cname_chain_too_deep, authoritative_disagreement, resolver_divergence, managed_delegation_missingThe specification clause the zone violates, e.g. "RFC 1034 §3.6.2".
What this actually does to mail for this domain, in plain language.
Which record to delete and which to keep, stated concretely enough to act on.
The offending record values, verbatim as published.
Every authoritative nameserver queried and exactly what it returned.
items
Independent public resolvers queried and exactly what each returned.
items
How many detection runs have observed this conflict.
The host a customer CNAMEs default._bimi.{domain} to for Palisade-served BIMI.
The fully-formed BIMI TXT value, populated whenever bimi_options.logo is set (via asset ingestion or a direct bimi_options update). The a= tag is included only when a certificate URL is also set. Customers who prefer not to delegate via CNAME can publish this value at default._bimi.{domain} themselves.
00 · Max: 1000 · Max: 1000 · Max: 100Group
properties
Returns only tasks with status "open"
Task
properties
The domain audit score as it stands now.
0 · Max: 100How much of the domain score completing this ticket wins back, by the same scoring the domain overview shows. 0 for ticket types the score does not measure. Present only with expand[]=domain, since it depends on the domain as it stands now.
0properties
properties
SENDING_TOOL, MAILBOX_PROVIDER, VPS_PROVIDER, SECURITY_PROVIDER, EMAIL_RELAYNOT_FORWARDER, FORWARDER, FORWARDER_ONLYNONE, RARE, FULLitems
DIRECT, SUBDOMAIN, MANAGED_SUBDOMAINproperties
properties
properties
items
TXT, CNAME, MXNONE, RARE, FULLBETA: Only expandable for GET /tasks/:id. Can contain instructions sometimes.
properties
items
TXT, CNAMEWhere the task sits in the email-authentication rollout, lower first: 10 DMARC setup, 20 foundation records, 30 SPF/DKIM alignment, 40 cleanup, 50 enforcement, 60 hardening. Separate from priority, which is urgency; sequence orders tasks of equal priority, since an alignment task cannot be worked before DMARC reporting exists to show the failure.
open, snoozed, canceled, dismissed, pending, donecleanup_spf_record, confirm_source, lockdown_domain, reduce_spf_lookups, set_up_dmarc_record, source_failing_dkim, source_failing_spf, set_up_mx_record, set_up_spf_record, update_dmarc_record, update_ttl, set_up_mta_sts, set_up_tls_rpt, resolve_dns_conflict, review_unused_sender, cleanup_sender_records, fix_mx_certificate, renew_vmc_certificate, dkim_selector_not_imported, set_up_bimiWhy a done ticket closed. 'verified': Palisade's own check found the problem gone. 'manual': a person or an API caller marked it done and nothing was checked. Null on a ticket that is not done, and on one closed before the reason was first recorded. More values may be added, so treat an unknown one as unspecified.
verified, manualWhen the domain first reached the "setup" monitoring status and DMARC report collection began.
The first day (yyyy-MM-dd) a DMARC aggregate report was actually received for this domain. The honest denominator for any activity claim: nothing before this day was observable, so a domain monitored for a week can never truthfully read as quiet for ninety days. Null until the first report arrives.
Update a domain
/domains/{id}requires authPath parameters
Headers
2025-04-30, unstableRequest body
properties
none, quarantine, reject0 · Max: 100none, quarantine, reject, sameproperties
properties
Example request
curl -X POST "https://api.palisade.email/domains/<id>" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30" \
-H "Content-Type: application/json" \
-d '{
"group_id": "5cf10a30-0b0c-4e05-9e68-6cbfd7d3c2a1",
"is_parked": true,
"dmarc_options": {
"additional_emails": [
"user@example.com"
],
"legacy_ruf_emails": [
"user@example.com"
],
"policy": "none",
"pct": 0,
"sp": "none",
"strict_spf": true,
"strict_dkim": true
},
"spf_options": {
"force_flattening": true,
"enabled": true,
"mechanism_descriptions": {}
},
"dmarc_setup_at": "2025-01-15T12:00:00.000Z",
"target_spf": "string",
"bimi_options": {
"enabled": true,
"logo": "https://example.com",
"certificate": "https://example.com"
},
"backfill_tickets": true
}'
Responses
Success
Response body
properties
none, quarantine, reject0 · Max: 100none, quarantine, reject, sameproperties
properties
unknown, syncing, ready, errorunknown, syncing, ready, errorunknown, syncing, ready, errorunknown, syncing, ready, errorunknown, syncing, ready, errorWhen each managed record last entered the "syncing" status. For dmarc, falls back to dmarc_setup_at when the transition predates tracking; other records are null when they have never synced or the transition predates tracking. Useful for estimating how long a "syncing" record has been waiting on DNS propagation.
properties
drifted, none, pending, setup, failednameservers_unresolvable, dmarc_record_missing, dmarc_record_added_as_txt_not_cname, dmarc_record_on_parent_only, dmarc_record_missing_palisade_rua, dmarc_record_invalid, dmarc_multiple_recordsDmarcSetupFailureDetail
Open tickets on this domain. Opportunity tickets such as set_up_bimi are not counted, and expand[]=tasks leaves them out to match.
0Priority of the most urgent open task on this domain, on the same inverted scale as a task's own priority: 0 critical, 1 high, 2 medium, 3 low. Null when the domain has no open tasks. Sort on "severity" to order domains by it.
0 · Max: 30 · Max: 100Risk band the score falls in: critical, bad, good, or great. The same banding the dashboard shows, so clients do not have to reimplement the thresholds.
critical, bad, good, greatproperties
Why managed_dns_status.bimi is "error". "setup_timeout" means the customer CNAME was never detected within the verification window (setup was never completed); "drift" means a previously verified CNAME stopped pointing at Palisade; "record_conflict" means default._bimi holds conflicting records — see dns_conflicts. Null when there is no error or the error predates reason tracking.
setup_timeout, drift, certificate_invalid, record_conflict, delegation_missing, publish_failed, dkim_key_error, check_failedWhy managed_dns_status.bimi is "error". "setup_timeout" means the customer CNAME was never detected within the verification window (setup was never completed); "drift" means a previously verified CNAME stopped pointing at Palisade; "record_conflict" means default._bimi holds conflicting records — see dns_conflicts. Null when there is no error or the error predates reason tracking.
Why managed_dns_status.bimi is "error". "setup_timeout" means the customer CNAME was never detected within the verification window (setup was never completed); "drift" means a previously verified CNAME stopped pointing at Palisade; "record_conflict" means default._bimi holds conflicting records — see dns_conflicts. Null when there is no error or the error predates reason tracking.
Why managed_dns_status.bimi is "error". "setup_timeout" means the customer CNAME was never detected within the verification window (setup was never completed); "drift" means a previously verified CNAME stopped pointing at Palisade; "record_conflict" means default._bimi holds conflicting records — see dns_conflicts. Null when there is no error or the error predates reason tracking.
Why managed_dns_status.bimi is "error". "setup_timeout" means the customer CNAME was never detected within the verification window (setup was never completed); "drift" means a previously verified CNAME stopped pointing at Palisade; "record_conflict" means default._bimi holds conflicting records — see dns_conflicts. Null when there is no error or the error predates reason tracking.
Unresolved record conflicts observed at labels Palisade manages or monitors for this domain. Empty for a healthy domain. Each entry quotes the offending records verbatim along with what every authoritative nameserver and public resolver returned, so it can be acted on without a second investigation.
DnsConflict
The exact DNS name the conflicting records sit at.
dmarc, spf, bimi, mta_sts, dkimcname_with_other_data, multiple_dmarc_records, multiple_spf_records, multiple_bimi_records, cname_target_unresolvable, cname_chain_too_deep, authoritative_disagreement, resolver_divergence, managed_delegation_missingThe specification clause the zone violates, e.g. "RFC 1034 §3.6.2".
What this actually does to mail for this domain, in plain language.
Which record to delete and which to keep, stated concretely enough to act on.
The offending record values, verbatim as published.
Every authoritative nameserver queried and exactly what it returned.
items
Independent public resolvers queried and exactly what each returned.
items
How many detection runs have observed this conflict.
The host a customer CNAMEs default._bimi.{domain} to for Palisade-served BIMI.
The fully-formed BIMI TXT value, populated whenever bimi_options.logo is set (via asset ingestion or a direct bimi_options update). The a= tag is included only when a certificate URL is also set. Customers who prefer not to delegate via CNAME can publish this value at default._bimi.{domain} themselves.
00 · Max: 1000 · Max: 1000 · Max: 100When the domain first reached the "setup" monitoring status and DMARC report collection began.
The first day (yyyy-MM-dd) a DMARC aggregate report was actually received for this domain. The honest denominator for any activity claim: nothing before this day was observable, so a domain monitored for a week can never truthfully read as quiet for ninety days. Null until the first report arrives.
Delete a domain
/domains/{id}requires authPath parameters
Headers
2025-04-30, unstableExample request
curl -X DELETE "https://api.palisade.email/domains/<id>" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Deleted
Response body
Add domains in bulk
/domains/bulkrequires authHeaders
2025-04-30, unstableRequest body
items
Example request
curl -X POST "https://api.palisade.email/domains/bulk" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30" \
-H "Content-Type: application/json" \
-d '{
"domains": [
{
"url": "string",
"group_id": "5cf10a30-0b0c-4e05-9e68-6cbfd7d3c2a1"
}
]
}'
Responses
Success
Response body
How many domains were created.
How many entries could not be created.
One entry per submitted domain, in request order. Entries are independent: a failure here does not roll back the domains that succeeded, and the response is 200 even when every entry failed, so inspect "failed" rather than the status code.
items
The domain from the request, echoed in the order it was sent.
created, failedThe created domain, or null when this entry failed.
properties
properties
none, quarantine, reject0 · Max: 100none, quarantine, reject, sameproperties
properties
unknown, syncing, ready, errorunknown, syncing, ready, errorunknown, syncing, ready, errorunknown, syncing, ready, errorunknown, syncing, ready, errorWhen each managed record last entered the "syncing" status. For dmarc, falls back to dmarc_setup_at when the transition predates tracking; other records are null when they have never synced or the transition predates tracking. Useful for estimating how long a "syncing" record has been waiting on DNS propagation.
properties
drifted, none, pending, setup, failednameservers_unresolvable, dmarc_record_missing, dmarc_record_added_as_txt_not_cname, dmarc_record_on_parent_only, dmarc_record_missing_palisade_rua, dmarc_record_invalid, dmarc_multiple_recordsDmarcSetupFailureDetail
Open tickets on this domain. Opportunity tickets such as set_up_bimi are not counted, and expand[]=tasks leaves them out to match.
0Priority of the most urgent open task on this domain, on the same inverted scale as a task's own priority: 0 critical, 1 high, 2 medium, 3 low. Null when the domain has no open tasks. Sort on "severity" to order domains by it.
0 · Max: 30 · Max: 100Risk band the score falls in: critical, bad, good, or great. The same banding the dashboard shows, so clients do not have to reimplement the thresholds.
critical, bad, good, greatproperties
Why managed_dns_status.bimi is "error". "setup_timeout" means the customer CNAME was never detected within the verification window (setup was never completed); "drift" means a previously verified CNAME stopped pointing at Palisade; "record_conflict" means default._bimi holds conflicting records — see dns_conflicts. Null when there is no error or the error predates reason tracking.
setup_timeout, drift, certificate_invalid, record_conflict, delegation_missing, publish_failed, dkim_key_error, check_failedWhy managed_dns_status.bimi is "error". "setup_timeout" means the customer CNAME was never detected within the verification window (setup was never completed); "drift" means a previously verified CNAME stopped pointing at Palisade; "record_conflict" means default._bimi holds conflicting records — see dns_conflicts. Null when there is no error or the error predates reason tracking.
Why managed_dns_status.bimi is "error". "setup_timeout" means the customer CNAME was never detected within the verification window (setup was never completed); "drift" means a previously verified CNAME stopped pointing at Palisade; "record_conflict" means default._bimi holds conflicting records — see dns_conflicts. Null when there is no error or the error predates reason tracking.
Why managed_dns_status.bimi is "error". "setup_timeout" means the customer CNAME was never detected within the verification window (setup was never completed); "drift" means a previously verified CNAME stopped pointing at Palisade; "record_conflict" means default._bimi holds conflicting records — see dns_conflicts. Null when there is no error or the error predates reason tracking.
Why managed_dns_status.bimi is "error". "setup_timeout" means the customer CNAME was never detected within the verification window (setup was never completed); "drift" means a previously verified CNAME stopped pointing at Palisade; "record_conflict" means default._bimi holds conflicting records — see dns_conflicts. Null when there is no error or the error predates reason tracking.
Unresolved record conflicts observed at labels Palisade manages or monitors for this domain. Empty for a healthy domain. Each entry quotes the offending records verbatim along with what every authoritative nameserver and public resolver returned, so it can be acted on without a second investigation.
DnsConflict
The exact DNS name the conflicting records sit at.
dmarc, spf, bimi, mta_sts, dkimcname_with_other_data, multiple_dmarc_records, multiple_spf_records, multiple_bimi_records, cname_target_unresolvable, cname_chain_too_deep, authoritative_disagreement, resolver_divergence, managed_delegation_missingThe specification clause the zone violates, e.g. "RFC 1034 §3.6.2".
What this actually does to mail for this domain, in plain language.
Which record to delete and which to keep, stated concretely enough to act on.
The offending record values, verbatim as published.
Every authoritative nameserver queried and exactly what it returned.
items
Independent public resolvers queried and exactly what each returned.
items
How many detection runs have observed this conflict.
The host a customer CNAMEs default._bimi.{domain} to for Palisade-served BIMI.
The fully-formed BIMI TXT value, populated whenever bimi_options.logo is set (via asset ingestion or a direct bimi_options update). The a= tag is included only when a certificate URL is also set. Customers who prefer not to delegate via CNAME can publish this value at default._bimi.{domain} themselves.
00 · Max: 1000 · Max: 1000 · Max: 100When the domain first reached the "setup" monitoring status and DMARC report collection began.
The first day (yyyy-MM-dd) a DMARC aggregate report was actually received for this domain. The honest denominator for any activity claim: nothing before this day was observable, so a domain monitored for a week can never truthfully read as quiet for ninety days. Null until the first report arrives.
Why this entry failed, or null when it succeeded.
properties
Upload BIMI assets
/domains/{id}/bimi/assetsrequires authIngests a Verified Mark Certificate (VMC), extracts and verifies the logotype SVG embedded in the certificate, and hosts the matched certificate + logo pair at per-domain asset URLs with a short content-derived version suffix ({domain}/bimi/logo-{v}.svg and {domain}/bimi/certchain-{v}.pem). Re-posting the same PEM returns the same URLs; a new PEM gets fresh URLs so caches never serve stale assets.
Path parameters
Headers
2025-04-30, unstableRequest body
The VMC as a PEM string. Alternative to the multipart certificate file part.
1An https URL to fetch the VMC PEM from. Alternative to the multipart certificate file part.
Example request
curl -X POST "https://api.palisade.email/domains/<id>/bimi/assets" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30" \
-H "Content-Type: application/json" \
-d '{
"certificate_pem": "string",
"certificate_url": "https://example.com"
}'
Responses
Success
Response body
The SVG hosted at logo_url was recovered from the certificate's logotype extension and matches the digest the certificate asserts. This covers the logo only — it says nothing about whether the certificate chain validates. Read chain_verified for that.
tiny-psThe hosted certificate chain was verified end to end: every signature checks out, no certificate in the path is expired, and the path terminates in a pinned BIMI trust anchor. Uploads that cannot reach this state are rejected, so a 200 response always carries true.
How many certificates the hosted chain contains, counting the VMC leaf, intermediates and root.
0True when the uploaded PEM was missing certificates and Palisade completed the chain (fetching the intermediate from the certificate's Authority Information Access endpoint and appending the pinned root) before hosting it. The hosted chain, not the uploaded one, is what certificate_url serves.
Common name of the pinned VMC root the hosted chain terminates in.
The leaf certificate's subjectAltName covers the domain the assets were attached to.
When the VMC leaf expires. VMCs are one-year certificates, so this is worth tracking.
Non-fatal observations about the certificate. "vmc-mark-type-oid-missing" means the leaf does not carry the VMC mark-type OIDs under 1.3.6.1.4.1.53087, which is certificate-authority dependent and does not block hosting.
properties
Certificate rejected
Response body
bimi_certificate_invalidpem_parse_failed, not_a_vmc, logotype_missing, logo_hash_mismatch, svg_not_tiny_ps, incomplete_chain, chain_untrusted, chain_expired, chain_signature_invalid, certificate_not_yet_valid, san_mismatch, contains_private_keyGet DNS records
/domains/{id}/dns-recordsrequires authReturns the consolidated, server-computed list of DNS records to publish for this domain, covering every enabled Palisade-managed feature (DMARC, SPF, DKIM, MTA-STS, TLS-RPT, BIMI) with per-record verification status. Records that are not yet verified are compared against live DNS, so "action" reflects what is actually published and "already_published" identifies records that need no change. Also reports the detected DNS provider hosting the domain, resolved from its live NS records, so the records can be published with a matching DNS integration.
Path parameters
Headers
2025-04-30, unstableExample request
curl "https://api.palisade.email/domains/<id>/dns-records" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
DnsRecord
dmarc, spf, dkim, mta_sts, mta_sts_policy, tls_rpt, bimiTXT, CNAME, NSFully qualified record name.
Record name relative to the domain apex; "@" designates the apex itself.
Recommended TTL in seconds.
0How to publish this record, derived from what is currently live in DNS. "create" means nothing serving this purpose exists at the host yet; "replace" means a record for this purpose already occupies the host and must be overwritten with this value; "delete" means the record must be removed. When already_published is true the record is already correct and "replace" would be a no-op, so use already_published to decide whether to act at all.
create, replace, deleteFalse for records that improve an enabled feature but are not needed for it to function.
pending, verifying, verified, driftedTrue when live DNS already serves exactly this value, so the record can be skipped. False when it is missing or serving something else. Null when the live lookup could not be completed, in which case "action" falls back to a static, type-derived value and should be treated as a best-effort hint.
True when every required record has status "verified".
Risks to resolve before publishing these records. Empty in the normal case. Read these before applying anything: publishing an enforcing DMARC policy on a domain with no working SPF or DKIM causes receivers to reject or quarantine its mail.
DnsRecordWarning
Stable identifier for the warning, safe to branch on.
Human-readable explanation of the risk.
Where the domain's DNS is hosted, so the records can be published with a matching DNS tool, connector, or provider API. This is the DNS host, which is often not the registrar reported in "registrar".
DetectedDnsProvider
Identifier of the DNS provider hosting the domain, derived from its live NS records. Deliberately an open set: ids recognized today are cloudflare, route53, godaddy, azure, google, namecheap, digitalocean, vercel, dnsimple, gandi, ovh, name.com, porkbun, hetzner, linode, networksolutions, microsoft365, wix, squarespace, ionos, hostinger, siteground, bluehost, hostgator, dreamhost, dnsmadeeasy, akamai, rackspace, cloudns, comodo, easydns, encirca, webnames, whc, rebel, register.com, hover, namesilo, dynadot, spaceship, one.com, enom, wordpress.com, hurricane-electric, and more are added over time, so treat an unfamiliar id the same as null rather than rejecting the response. Null when the nameservers do not match a known provider, disagree with each other, or could not be resolved — in that case use "nameservers" to decide, and never assume a provider.
The nameservers the domain is delegated to. Empty when the lookup failed or returned nothing.
Verify a domain
/domains/{id}/verifyrequires authQueues full domain monitoring and synchronously re-checks records that are still propagating. "results" reports the purposes confirmed during this pass using the same slugs as GET /domains/{id}/dns-records.
Path parameters
Headers
2025-04-30, unstableExample request
curl -X POST "https://api.palisade.email/domains/<id>/verify" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
Outcome of the synchronous verification pass, keyed by the same purpose slugs as GET /domains/{id}/dns-records. A purpose is present only when it was confirmed during this pass; absence means it was not confirmed (it may already be verified, or still propagating). tls_rpt and mta_sts_policy are not covered by the synchronous pass and never appear.
VerifyResults
Verify SPF for a domain
/domains/{id}/verify/spfrequires authQueues SPF verification and synchronously re-checks records that are still propagating. "results" reports the purposes confirmed during this pass using the same slugs as GET /domains/{id}/dns-records.
Path parameters
Headers
2025-04-30, unstableExample request
curl -X POST "https://api.palisade.email/domains/<id>/verify/spf" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
Outcome of the synchronous verification pass, keyed by the same purpose slugs as GET /domains/{id}/dns-records. A purpose is present only when it was confirmed during this pass; absence means it was not confirmed (it may already be verified, or still propagating). tls_rpt and mta_sts_policy are not covered by the synchronous pass and never appear.
VerifyResults
Verify DKIM for a domain
/domains/{id}/verify/dkimrequires authQueues DKIM verification and synchronously re-checks records that are still propagating. "results" reports the purposes confirmed during this pass using the same slugs as GET /domains/{id}/dns-records.
Path parameters
Headers
2025-04-30, unstableExample request
curl -X POST "https://api.palisade.email/domains/<id>/verify/dkim" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
Outcome of the synchronous verification pass, keyed by the same purpose slugs as GET /domains/{id}/dns-records. A purpose is present only when it was confirmed during this pass; absence means it was not confirmed (it may already be verified, or still propagating). tls_rpt and mta_sts_policy are not covered by the synchronous pass and never appear.
VerifyResults
Enable hosted DMARC
/domains/{id}/hosted-dmarcrequires authRebuilds the Palisade-hosted DMARC record from the domain's current policy, publishes it, and returns the CNAME to point _dmarc at. Call this before showing anyone the CNAME: the delegation target is otherwise whatever was written when the domain was created, so a domain whose owner tightened their own DMARC policy since then would be switched onto a weaker one. Nothing is written to the database unless the publish succeeds, so a failure is safe to retry, and calling it on a domain that is already hosted changes nothing and answers hosted_dmarc_active: true.
Path parameters
Headers
2025-04-30, unstableExample request
curl -X POST "https://api.palisade.email/domains/<id>/hosted-dmarc" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
False until the hosted CNAME resolves in live DNS. Publish "record" and Palisade flips this to true on its own; true already on a domain that was hosted before the call.
The CNAME to publish at _dmarc.<domain>, rebuilt from the domain's current DMARC policy. Delete any DMARC TXT record still sitting at the same host, which conflicts with it.
properties
dmarc, spf, dkim, mta_sts, mta_sts_policy, tls_rpt, bimiTXT, CNAME, NSFully qualified record name.
Record name relative to the domain apex; "@" designates the apex itself.
Recommended TTL in seconds.
0How to publish this record, derived from what is currently live in DNS. "create" means nothing serving this purpose exists at the host yet; "replace" means a record for this purpose already occupies the host and must be overwritten with this value; "delete" means the record must be removed. When already_published is true the record is already correct and "replace" would be a no-op, so use already_published to decide whether to act at all.
create, replace, deleteFalse for records that improve an enabled feature but are not needed for it to function.
pending, verifying, verified, driftedTrue when live DNS already serves exactly this value, so the record can be skipped. False when it is missing or serving something else. Null when the live lookup could not be completed, in which case "action" falls back to a static, type-derived value and should be treated as a best-effort hint.
Domain
properties
none, quarantine, reject0 · Max: 100none, quarantine, reject, sameproperties
properties
unknown, syncing, ready, errorunknown, syncing, ready, errorunknown, syncing, ready, errorunknown, syncing, ready, errorunknown, syncing, ready, errorWhen each managed record last entered the "syncing" status. For dmarc, falls back to dmarc_setup_at when the transition predates tracking; other records are null when they have never synced or the transition predates tracking. Useful for estimating how long a "syncing" record has been waiting on DNS propagation.
properties
drifted, none, pending, setup, failednameservers_unresolvable, dmarc_record_missing, dmarc_record_added_as_txt_not_cname, dmarc_record_on_parent_only, dmarc_record_missing_palisade_rua, dmarc_record_invalid, dmarc_multiple_recordsDmarcSetupFailureDetail
Open tickets on this domain. Opportunity tickets such as set_up_bimi are not counted, and expand[]=tasks leaves them out to match.
0Priority of the most urgent open task on this domain, on the same inverted scale as a task's own priority: 0 critical, 1 high, 2 medium, 3 low. Null when the domain has no open tasks. Sort on "severity" to order domains by it.
0 · Max: 30 · Max: 100Risk band the score falls in: critical, bad, good, or great. The same banding the dashboard shows, so clients do not have to reimplement the thresholds.
critical, bad, good, greatproperties
Why managed_dns_status.bimi is "error". "setup_timeout" means the customer CNAME was never detected within the verification window (setup was never completed); "drift" means a previously verified CNAME stopped pointing at Palisade; "record_conflict" means default._bimi holds conflicting records — see dns_conflicts. Null when there is no error or the error predates reason tracking.
setup_timeout, drift, certificate_invalid, record_conflict, delegation_missing, publish_failed, dkim_key_error, check_failedWhy managed_dns_status.bimi is "error". "setup_timeout" means the customer CNAME was never detected within the verification window (setup was never completed); "drift" means a previously verified CNAME stopped pointing at Palisade; "record_conflict" means default._bimi holds conflicting records — see dns_conflicts. Null when there is no error or the error predates reason tracking.
Why managed_dns_status.bimi is "error". "setup_timeout" means the customer CNAME was never detected within the verification window (setup was never completed); "drift" means a previously verified CNAME stopped pointing at Palisade; "record_conflict" means default._bimi holds conflicting records — see dns_conflicts. Null when there is no error or the error predates reason tracking.
Why managed_dns_status.bimi is "error". "setup_timeout" means the customer CNAME was never detected within the verification window (setup was never completed); "drift" means a previously verified CNAME stopped pointing at Palisade; "record_conflict" means default._bimi holds conflicting records — see dns_conflicts. Null when there is no error or the error predates reason tracking.
Why managed_dns_status.bimi is "error". "setup_timeout" means the customer CNAME was never detected within the verification window (setup was never completed); "drift" means a previously verified CNAME stopped pointing at Palisade; "record_conflict" means default._bimi holds conflicting records — see dns_conflicts. Null when there is no error or the error predates reason tracking.
Unresolved record conflicts observed at labels Palisade manages or monitors for this domain. Empty for a healthy domain. Each entry quotes the offending records verbatim along with what every authoritative nameserver and public resolver returned, so it can be acted on without a second investigation.
DnsConflict
The exact DNS name the conflicting records sit at.
dmarc, spf, bimi, mta_sts, dkimcname_with_other_data, multiple_dmarc_records, multiple_spf_records, multiple_bimi_records, cname_target_unresolvable, cname_chain_too_deep, authoritative_disagreement, resolver_divergence, managed_delegation_missingThe specification clause the zone violates, e.g. "RFC 1034 §3.6.2".
What this actually does to mail for this domain, in plain language.
Which record to delete and which to keep, stated concretely enough to act on.
The offending record values, verbatim as published.
Every authoritative nameserver queried and exactly what it returned.
items
Independent public resolvers queried and exactly what each returned.
items
How many detection runs have observed this conflict.
The host a customer CNAMEs default._bimi.{domain} to for Palisade-served BIMI.
The fully-formed BIMI TXT value, populated whenever bimi_options.logo is set (via asset ingestion or a direct bimi_options update). The a= tag is included only when a certificate URL is also set. Customers who prefer not to delegate via CNAME can publish this value at default._bimi.{domain} themselves.
00 · Max: 1000 · Max: 1000 · Max: 100Group
properties
Returns only tasks with status "open"
Task
properties
The domain audit score as it stands now.
0 · Max: 100How much of the domain score completing this ticket wins back, by the same scoring the domain overview shows. 0 for ticket types the score does not measure. Present only with expand[]=domain, since it depends on the domain as it stands now.
0properties
properties
SENDING_TOOL, MAILBOX_PROVIDER, VPS_PROVIDER, SECURITY_PROVIDER, EMAIL_RELAYNOT_FORWARDER, FORWARDER, FORWARDER_ONLYNONE, RARE, FULLitems
DIRECT, SUBDOMAIN, MANAGED_SUBDOMAINproperties
properties
properties
NONE, RARE, FULLBETA: Only expandable for GET /tasks/:id. Can contain instructions sometimes.
properties
items
TXT, CNAMEWhere the task sits in the email-authentication rollout, lower first: 10 DMARC setup, 20 foundation records, 30 SPF/DKIM alignment, 40 cleanup, 50 enforcement, 60 hardening. Separate from priority, which is urgency; sequence orders tasks of equal priority, since an alignment task cannot be worked before DMARC reporting exists to show the failure.
open, snoozed, canceled, dismissed, pending, donecleanup_spf_record, confirm_source, lockdown_domain, reduce_spf_lookups, set_up_dmarc_record, source_failing_dkim, source_failing_spf, set_up_mx_record, set_up_spf_record, update_dmarc_record, update_ttl, set_up_mta_sts, set_up_tls_rpt, resolve_dns_conflict, review_unused_sender, cleanup_sender_records, fix_mx_certificate, renew_vmc_certificate, dkim_selector_not_imported, set_up_bimiWhy a done ticket closed. 'verified': Palisade's own check found the problem gone. 'manual': a person or an API caller marked it done and nothing was checked. Null on a ticket that is not done, and on one closed before the reason was first recorded. More values may be added, so treat an unknown one as unspecified.
verified, manualWhen the domain first reached the "setup" monitoring status and DMARC report collection began.
The first day (yyyy-MM-dd) a DMARC aggregate report was actually received for this domain. The honest denominator for any activity claim: nothing before this day was observable, so a domain monitored for a week can never truthfully read as quiet for ninety days. Null until the first report arrives.
Get the remediation plan
/domains/{domainId}/planrequires authThe work Palisade has planned for this domain, as the four stages of the DMARC journey with the steps each is made of. A step Palisade has already opened tickets for carries their ids in task_ids and is readable through GET /tasks; a step it has not carries none, and is work it expects to open later. upcoming_steps is the shortlist of what comes next, which is what the app shows under a domain's open tickets. Read /tasks for what is actionable now and this for what is coming. Computed on read, so nothing here is a stored record and none of it emits webhooks.
Path parameters
Headers
2025-04-30, unstableExample request
curl "https://api.palisade.email/domains/<domainId>/plan" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
Saved onboarding findings, including those without an actionable ticket. Not a fresh DNS audit.
properties
items
open, verifying, snoozed, ticket_completed, upcoming, waiting, optional, reviewitems
The task types that would carry this finding out, matching "type" on the Task object and "task_type" on a plan step. A type listed here is not always opened: update_ttl and set_up_tls_rpt, for example, never are. Empty when no task type covers the finding, such as BIMI or a DKIM problem with one selector.
items
cleanup_spf_record, confirm_source, lockdown_domain, reduce_spf_lookups, set_up_dmarc_record, source_failing_dkim, source_failing_spf, set_up_mx_record, set_up_spf_record, update_dmarc_record, update_ttl, set_up_mta_sts, set_up_tls_rpt, resolve_dns_conflict, review_unused_sender, cleanup_sender_records, fix_mx_certificate, renew_vmc_certificate, dkim_selector_not_imported, set_up_bimiThe domain this plan is for.
True when the domain is parked. A parked domain is monitored but has no journey to work through.
False when the plan is not being worked because the organization is on a plan without the agent. upcoming_steps is empty in that case, because Palisade will not open those tasks.
The number of the stage being worked now, or null when none is current.
The four stages of the DMARC journey, in order.
PlanStage
Position in the journey, 1 through 4.
Stable identifier: "setup", "alignment", "enforcement" or "monitoring".
"completed" when the stage is done, "current" for the one being worked, "pending" for one not started.
completed, current, pendingThe work this stage is made of. Empty for a parked domain.
PlanStep
Stable identifier for this step, safe to branch on - for example "dmarc-setup", "alignment-spf" or "dmarc-reject-full". Steps are added over time; existing keys keep their meaning.
The type of task this step opens as, matching "type" on the Task object. Null for a step that is never a task, such as ongoing monitoring.
cleanup_spf_record, confirm_source, lockdown_domain, reduce_spf_lookups, set_up_dmarc_record, source_failing_dkim, source_failing_spf, set_up_mx_record, set_up_spf_record, update_dmarc_record, update_ttl, set_up_mta_sts, set_up_tls_rpt, resolve_dns_conflict, review_unused_sender, cleanup_sender_records, fix_mx_certificate, renew_vmc_certificate, dkim_selector_not_imported, set_up_bimiWhat the step asks for, in plain language.
Why the step matters.
Severity on the same scale as a task: 0 critical, 1 high, 2 medium, 3 low. When tasks already exist for this step, this is the most severe of theirs.
How many points of the domain's audit score completing this step would win back. 0 when none.
"in_progress" when Palisade has already opened tasks for this step, listed in task_ids. "upcoming" when it has not, meaning there is nothing to action yet.
in_progress, upcomingOpen and pending tasks that carry out this step, readable through GET /tasks/{id}. Empty for an upcoming step. A step covering sending sources has one task per source, so this can hold several.
Improvements worth making at this stage that Palisade does not require.
PlanOptionalStep
Stable identifier for the optional step, for example "enable-hosted-spf".
True when Palisade actively suggests it for this domain right now.
The steps Palisade expects to work next: the next stage's steps, when that stage has not started. These are a subset of stages[].steps, always with status "upcoming", and are what the app shows below the open tasks. Empty for a parked domain, when the agent is not proposing work, and once the journey is finished.
PlanStep
Stable identifier for this step, safe to branch on - for example "dmarc-setup", "alignment-spf" or "dmarc-reject-full". Steps are added over time; existing keys keep their meaning.
The type of task this step opens as, matching "type" on the Task object. Null for a step that is never a task, such as ongoing monitoring.
cleanup_spf_record, confirm_source, lockdown_domain, reduce_spf_lookups, set_up_dmarc_record, source_failing_dkim, source_failing_spf, set_up_mx_record, set_up_spf_record, update_dmarc_record, update_ttl, set_up_mta_sts, set_up_tls_rpt, resolve_dns_conflict, review_unused_sender, cleanup_sender_records, fix_mx_certificate, renew_vmc_certificate, dkim_selector_not_imported, set_up_bimiWhat the step asks for, in plain language.
Why the step matters.
Severity on the same scale as a task: 0 critical, 1 high, 2 medium, 3 low. When tasks already exist for this step, this is the most severe of theirs.
How many points of the domain's audit score completing this step would win back. 0 when none.
"in_progress" when Palisade has already opened tasks for this step, listed in task_ids. "upcoming" when it has not, meaning there is nothing to action yet.
in_progress, upcomingOpen and pending tasks that carry out this step, readable through GET /tasks/{id}. Empty for an upcoming step. A step covering sending sources has one task per source, so this can hold several.
DomainSource
List confirmed senders
/domains/{domainId}/sourcesrequires authPath parameters
Headers
2025-04-30, unstableExample request
curl "https://api.palisade.email/domains/<domainId>/sources" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
DomainSource
The catalogue source this sender was matched to, or null when it is not one Palisade recognises. Lets a caller line a sender up with the SPF include or DKIM key it belongs to.
The SPF mechanism discovery observed for this sender, when it saw one.
confirmed, discarded, requires_confirmationThe last day (YYYY-MM-DD) this sender was seen sending for the domain, across all recorded history rather than a recent window, so a sender silent for a year still reports the day it went quiet. Null when no sending has been recorded for it yet. Reported from daily aggregates that can trail live reporting by a few days, so treat it as a date rather than a timestamp. Only counts sending observed since the domain was added to Palisade.
The last day (YYYY-MM-DD) mail from this sender passed aligned SPF for the domain. Distinct from last_seen_at: a sender that still sends but no longer passes SPF has an SPF problem, not a disused include. Null when it has never passed aligned SPF in recorded history.
properties
properties
Confirm or update a sender
/domains/{domainId}/sources/{sourceId}requires authPath parameters
Headers
2025-04-30, unstableRequest body
confirmed, discarded, requires_confirmationExample request
curl -X POST "https://api.palisade.email/domains/<domainId>/sources/<sourceId>" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30" \
-H "Content-Type: application/json" \
-d '{
"confirmation_status": "confirmed"
}'
Responses
Success
Response body
The catalogue source this sender was matched to, or null when it is not one Palisade recognises. Lets a caller line a sender up with the SPF include or DKIM key it belongs to.
The SPF mechanism discovery observed for this sender, when it saw one.
confirmed, discarded, requires_confirmationThe last day (YYYY-MM-DD) this sender was seen sending for the domain, across all recorded history rather than a recent window, so a sender silent for a year still reports the day it went quiet. Null when no sending has been recorded for it yet. Reported from daily aggregates that can trail live reporting by a few days, so treat it as a date rather than a timestamp. Only counts sending observed since the domain was added to Palisade.
The last day (YYYY-MM-DD) mail from this sender passed aligned SPF for the domain. Distinct from last_seen_at: a sender that still sends but no longer passes SPF has an SPF problem, not a disused include. Null when it has never passed aligned SPF in recorded history.
properties
DkimKey
List DKIM keys
/domains/{domainId}/dkim-keysrequires authPath parameters
Query parameters
unknown, syncing, ready, errorHeaders
2025-04-30, unstableExample request
curl "https://api.palisade.email/domains/<domainId>/dkim-keys" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
DkimKey
TXT, CNAMEunknown, syncing, ready, errorWhy the last publish attempt failed, in terms a customer can act on. Null unless dns_status is error; cleared by the next successful publish.
properties
Add a DKIM key
/domains/{domainId}/dkim-keysrequires authPath parameters
Headers
2025-04-30, unstableRequest body
1TXT, CNAME1300 · Max: 86400Example request
curl -X POST "https://api.palisade.email/domains/<domainId>/dkim-keys" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30" \
-H "Content-Type: application/json" \
-d '{
"selector": "string",
"record_type": "TXT",
"value": "string",
"ttl": 300
}'
Responses
Success
Response body
TXT, CNAMEunknown, syncing, ready, errorWhy the last publish attempt failed, in terms a customer can act on. Null unless dns_status is error; cleared by the next successful publish.
Get a DKIM key
/domains/{domainId}/dkim-keys/{id}requires authPath parameters
Headers
2025-04-30, unstableExample request
curl "https://api.palisade.email/domains/<domainId>/dkim-keys/<id>" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
TXT, CNAMEunknown, syncing, ready, errorWhy the last publish attempt failed, in terms a customer can act on. Null unless dns_status is error; cleared by the next successful publish.
Update a DKIM key
/domains/{domainId}/dkim-keys/{id}requires authPath parameters
Headers
2025-04-30, unstableRequest body
1TXT, CNAME1300 · Max: 86400Example request
curl -X POST "https://api.palisade.email/domains/<domainId>/dkim-keys/<id>" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30" \
-H "Content-Type: application/json" \
-d '{
"selector": "string",
"record_type": "TXT",
"value": "string",
"ttl": 300
}'
Responses
Success
Response body
TXT, CNAMEunknown, syncing, ready, errorWhy the last publish attempt failed, in terms a customer can act on. Null unless dns_status is error; cleared by the next successful publish.
Delete a DKIM key
/domains/{domainId}/dkim-keys/{id}requires authPath parameters
Headers
2025-04-30, unstableExample request
curl -X DELETE "https://api.palisade.email/domains/<domainId>/dkim-keys/<id>" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
Reports
Get the DMARC summary
/domains/{domainId}/reports/summaryrequires authPath parameters
Query parameters
Reporting window, ending yesterday. Defaults to last_7_days.
last_7_days, last_14_days, last_30_daysHeaders
2025-04-30, unstableExample request
curl "https://api.palisade.email/domains/<domainId>/reports/summary" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
Id of the domain the summary is for.
The domain name the summary is for.
First day of the window, YYYY-MM-DD. Clamped to the earliest day the organization's plan retains report history for, so it can be later than the requested period alone implies.
Last day of the window, YYYY-MM-DD. Always yesterday: aggregate reports arrive a day in arrears, so a window ending today would read as a volume collapse.
Total messages reported in the window, across every compliance bucket.
Share of volume that passed DMARC, 0-100, rounded to two decimals, and 0 when the window has no volume. The denominator is volume, so forwarded and uncategorised traffic counts against it - which is why this reads lower than the last_14_days figure.
Share of volume that passed SPF, 0-100, rounded to two decimals, and 0 when the window has no volume.
Share of volume that passed DKIM, 0-100, rounded to two decimals, and 0 when the window has no volume.
Message counts by compliance bucket. They sum to volume.
properties
Messages that passed DMARC alignment.
Messages that failed DMARC. This is the number to drive to zero.
Messages the compliance categorizer attributed to forwarding.
Messages from a sending source Palisade could not identify.
Messages whose compliance is undetermined, including reports the categorizer has not processed yet.
The same number of days immediately before this window. It ends the day before this window starts, so its date_to is not yesterday.
properties
First day of the window, YYYY-MM-DD. Clamped to the earliest day the organization's plan retains report history for, so it can be later than the requested period alone implies.
Last day of the window, YYYY-MM-DD. No window ever includes today: aggregate reports arrive a day in arrears, so a window ending today would read as a volume collapse.
Total messages reported in the window, across every compliance bucket.
Share of volume that passed DMARC, 0-100, rounded to two decimals, and 0 when the window has no volume. The denominator is volume, so forwarded and uncategorised traffic counts against it - which is why this reads lower than the last_14_days figure.
Share of volume that passed SPF, 0-100, rounded to two decimals, and 0 when the window has no volume.
Share of volume that passed DKIM, 0-100, rounded to two decimals, and 0 when the window has no volume.
This window minus the previous one. Positive means the metric improved (or grew, for volume).
properties
Change in message volume against the previous window.
Change in DMARC pass rate, in percentage points, rounded to two decimals.
Change in SPF pass rate, in percentage points, rounded to two decimals.
Change in DKIM pass rate, in percentage points, rounded to two decimals.
The stored 14-day figures GET /domains/{id} reports. These count only compliant and non-compliant traffic, so they read higher than the window figures above on a domain with forwarding. A mismatch is the two definitions, not a fault.
properties
Messages counted over the last 14 days, as stored on the domain.
Share of that volume that passed DMARC, 0-100.
Share of that volume that passed SPF, 0-100.
Share of that volume that passed DKIM, 0-100.
The domain's DMARC policy state, in the same form GET /domains/{id} reports.
Monitoring state of the domain, in the same form GET /domains/{id} reports.
Whether Palisade currently recommends tightening the DMARC policy. This reports the recommendation Palisade has already computed - it is not a second, independent gate.
properties
"advance_recommended" when Palisade has an open policy-advancement task for the domain, "hold" when it has not opened one, and "at_maximum" when the domain is already at p=reject with pct=100.
advance_recommended, hold, at_maximumWhy Palisade does or does not recommend tightening the policy right now. When status is "advance_recommended", this is the advancement task's own description.
The UPDATE_DMARC_RECORD task carrying the recommendation, when Palisade has opened one.
Open and pending remediation tasks for this domain, most urgent first, capped at 10.
DmarcProbeTask
Task id. Read it with GET /tasks/{id}?expand[]=instructions for the fix Palisade has worked out.
What kind of problem the task describes.
cleanup_spf_record, confirm_source, lockdown_domain, reduce_spf_lookups, set_up_dmarc_record, source_failing_dkim, source_failing_spf, set_up_mx_record, set_up_spf_record, update_dmarc_record, update_ttl, set_up_mta_sts, set_up_tls_rpt, resolve_dns_conflict, review_unused_sender, cleanup_sender_records, fix_mx_certificate, renew_vmc_certificate, dkim_selector_not_imported, set_up_bimiLower is more urgent. 0 is the most urgent.
What is wrong, in plain language.
The sending source this task covers. Matches senders[].source_alias.
The sending domain the task is about, when it has one.
Total open and pending tasks, which may exceed the array length.
The single action Palisade suggests taking next.
List DMARC senders
/domains/{domainId}/reports/sendersrequires authPath parameters
Query parameters
Reporting window, ending yesterday. Defaults to last_7_days.
last_7_days, last_14_days, last_30_daysHow many senders to return, highest volume first. Maximum 20.
Headers
2025-04-30, unstableExample request
curl "https://api.palisade.email/domains/<domainId>/reports/senders" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
Total windowed volume across every sender, not just the ones returned.
Distinct senders seen in the window.
True when total_senders exceeds the returned list.
DmarcSender
Stable identifier for the sending source: a Palisade source id when the sender is recognised, otherwise the sending base domain, or "unknown". This is the key that links a sender to a task.
Display name when the source is recognised, otherwise source_alias.
False when DMARC reports show this sender but Palisade cannot identify it.
The header-from domains this source sent as, highest volume first, capped at 5.
Share of the domain's total windowed volume this sender accounts for.
Message counts by compliance bucket. They sum to volume.
properties
Messages that passed DMARC alignment.
Messages that failed DMARC. This is the number to drive to zero.
Messages the compliance categorizer attributed to forwarding.
Messages from a sending source Palisade could not identify.
Messages whose compliance is undetermined, including reports the categorizer has not processed yet.
True when the sender has non-compliant volume in the window.
An open or pending remediation task covering this sender, when one exists. Call GET /tasks/{id}?expand[]=instructions for the fix rather than improvising one.
cleanup_spf_record, confirm_source, lockdown_domain, reduce_spf_lookups, set_up_dmarc_record, source_failing_dkim, source_failing_spf, set_up_mx_record, set_up_spf_record, update_dmarc_record, update_ttl, set_up_mta_sts, set_up_tls_rpt, resolve_dns_conflict, review_unused_sender, cleanup_sender_records, fix_mx_certificate, renew_vmc_certificate, dkim_selector_not_imported, set_up_bimiDnsProvider
Detect the DNS provider
/dns-providers/detectrequires authDetect which DNS provider hosts a domain, from its live NS records. Returns a null provider when the nameservers match no known provider.
Query parameters
Headers
2025-04-30, unstableExample request
curl "https://api.palisade.email/dns-providers/detect" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
DnsSnapshot
List DNS snapshots
/domains/{domainId}/dns-snapshotsrequires authPath parameters
Query parameters
spf, dmarc, bimi, mx, dkim, ns, mta_sts, tls_rptHeaders
2025-04-30, unstableExample request
curl "https://api.palisade.email/domains/<domainId>/dns-snapshots" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
items
items
items
properties
Get a DNS snapshot
/domains/{domainId}/dns-snapshots/{id}requires authPath parameters
Query parameters
diffHeaders
2025-04-30, unstableExample request
curl "https://api.palisade.email/domains/<domainId>/dns-snapshots/<id>" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
items
items
properties
items
items
items
items
properties
properties
items
properties
properties
items
items
items
Group
List groups
/groupsrequires authQuery parameters
created_at, namedesc, ascdomainsHeaders
2025-04-30, unstableExample request
curl "https://api.palisade.email/groups" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
Group
properties
properties
Create a group
/groupsrequires authHeaders
2025-04-30, unstableRequest body
1Example request
curl -X POST "https://api.palisade.email/groups" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30" \
-H "Content-Type: application/json" \
-d '{
"name": "string"
}'
Responses
Success
Response body
Get a group
/groups/{id}Path parameters
Headers
2025-04-30, unstableExample request
curl "https://api.palisade.email/groups/<id>"
Responses
Success
Response body
properties
Update a group
/groups/{id}requires authPath parameters
Headers
2025-04-30, unstableRequest body
1Example request
curl -X POST "https://api.palisade.email/groups/<id>" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30" \
-H "Content-Type: application/json" \
-d '{
"name": "string",
"external_customer_id": "string",
"external_billing_entity_id": "string",
"backfill_tickets": true
}'
Responses
Success
Response body
Delete a group
/groups/{id}requires authPath parameters
Headers
2025-04-30, unstableExample request
curl -X DELETE "https://api.palisade.email/groups/<id>" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Deleted
Response body
Invitation
List pending invitations
/invitationsrequires authHeaders
2025-04-30, unstableExample request
curl "https://api.palisade.email/invitations" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
Invitation
properties
items
admin, editor, viewer[]properties
Invite a teammate
/invitationsrequires authHeaders
2025-04-30, unstableRequest body
The address to invite.
items
admin, editor, viewer1209600 · Min: 86400 · Max: 2592000Example request
curl -X POST "https://api.palisade.email/invitations" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30" \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"roles": [
"admin"
],
"groups": [
"5cf10a30-0b0c-4e05-9e68-6cbfd7d3c2a1"
],
"ttl_sec": 1209600
}'
Responses
Created
Response body
Invitation
properties
items
admin, editor, viewer[]invitation_domain_not_allowed: API-key callers only, the invitee email domain does not match any existing member email domain of the organization; contact support to add a new domain, and note that dashboard sessions are not subject to this check. invitation_invitee_exists: the email address already has a Palisade account, so an invitation would send it to a signup screen it cannot complete; use POST /members to add the existing account instead.
Response body
upstream_failure: the identity provider returned an error while creating the invitation. The invitation may still have been created without its email being sent; list invitations to check before retrying, since a retry creates a second invitation to the same address.
Response body
upstream_failureResend an invitation
/invitations/{id}/resendrequires authPath parameters
Headers
2025-04-30, unstableExample request
curl -X POST "https://api.palisade.email/invitations/<id>/resend" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
No Content
Response body
upstream_failure: the identity provider returned an error while replacing the invitation. The message says whether the old invitation still stands, was removed, or could not be checked; list invitations before retrying.
Response body
upstream_failureRevoke an invitation
/invitations/{id}requires authPath parameters
Headers
2025-04-30, unstableExample request
curl -X DELETE "https://api.palisade.email/invitations/<id>" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Deleted
Response body
Task
List tasks
/tasksrequires authBy default, the API returns 'open' and 'pending' tickets. To filter by other statuses, use the 'statuses' query parameter.
Query parameters
By default, we return OPEN and PENDING tasks.
open, snoozed, canceled, dismissed, pending, doneDefaults to 'priority', most urgent first, with ties broken by rollout stage then recency — so among equally urgent tickets, DMARC setup comes before the SPF and DKIM work that depends on its reports. 'sequence' walks the rollout outright: DMARC setup, foundation records, SPF/DKIM alignment, cleanup, enforcement, hardening. 'status' ranks pending tickets first, then open, snoozed, done, dismissed and canceled, breaking ties by priority, sequence, then most recent. 'resolved_at' orders by when a ticket was completed, most recent first when descending; tickets never completed sort last.
created_at, priority, resolved_at, sequence, statusdesc, ascdomain, sourceHeaders
2025-04-30, unstableExample request
curl "https://api.palisade.email/tasks" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
Task
properties
The domain audit score as it stands now.
0 · Max: 100How much of the domain score completing this ticket wins back, by the same scoring the domain overview shows. 0 for ticket types the score does not measure. Present only with expand[]=domain, since it depends on the domain as it stands now.
0properties
properties
SENDING_TOOL, MAILBOX_PROVIDER, VPS_PROVIDER, SECURITY_PROVIDER, EMAIL_RELAYNOT_FORWARDER, FORWARDER, FORWARDER_ONLYNONE, RARE, FULLitems
DIRECT, SUBDOMAIN, MANAGED_SUBDOMAINproperties
properties
properties
items
TXT, CNAME, MXNONE, RARE, FULLBETA: Only expandable for GET /tasks/:id. Can contain instructions sometimes.
properties
items
TXT, CNAMEWhere the task sits in the email-authentication rollout, lower first: 10 DMARC setup, 20 foundation records, 30 SPF/DKIM alignment, 40 cleanup, 50 enforcement, 60 hardening. Separate from priority, which is urgency; sequence orders tasks of equal priority, since an alignment task cannot be worked before DMARC reporting exists to show the failure.
open, snoozed, canceled, dismissed, pending, donecleanup_spf_record, confirm_source, lockdown_domain, reduce_spf_lookups, set_up_dmarc_record, source_failing_dkim, source_failing_spf, set_up_mx_record, set_up_spf_record, update_dmarc_record, update_ttl, set_up_mta_sts, set_up_tls_rpt, resolve_dns_conflict, review_unused_sender, cleanup_sender_records, fix_mx_certificate, renew_vmc_certificate, dkim_selector_not_imported, set_up_bimiWhy a done ticket closed. 'verified': Palisade's own check found the problem gone. 'manual': a person or an API caller marked it done and nothing was checked. Null on a ticket that is not done, and on one closed before the reason was first recorded. More values may be added, so treat an unknown one as unspecified.
verified, manualproperties
Get a task
/tasks/{id}requires authPath parameters
Query parameters
domain, instructions, sourceHeaders
2025-04-30, unstableExample request
curl "https://api.palisade.email/tasks/<id>" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
properties
The domain audit score as it stands now.
0 · Max: 100How much of the domain score completing this ticket wins back, by the same scoring the domain overview shows. 0 for ticket types the score does not measure. Present only with expand[]=domain, since it depends on the domain as it stands now.
0properties
properties
SENDING_TOOL, MAILBOX_PROVIDER, VPS_PROVIDER, SECURITY_PROVIDER, EMAIL_RELAYNOT_FORWARDER, FORWARDER, FORWARDER_ONLYNONE, RARE, FULLitems
DIRECT, SUBDOMAIN, MANAGED_SUBDOMAINproperties
properties
properties
items
TXT, CNAME, MXNONE, RARE, FULLBETA: Only expandable for GET /tasks/:id. Can contain instructions sometimes.
properties
items
TXT, CNAMEWhere the task sits in the email-authentication rollout, lower first: 10 DMARC setup, 20 foundation records, 30 SPF/DKIM alignment, 40 cleanup, 50 enforcement, 60 hardening. Separate from priority, which is urgency; sequence orders tasks of equal priority, since an alignment task cannot be worked before DMARC reporting exists to show the failure.
open, snoozed, canceled, dismissed, pending, donecleanup_spf_record, confirm_source, lockdown_domain, reduce_spf_lookups, set_up_dmarc_record, source_failing_dkim, source_failing_spf, set_up_mx_record, set_up_spf_record, update_dmarc_record, update_ttl, set_up_mta_sts, set_up_tls_rpt, resolve_dns_conflict, review_unused_sender, cleanup_sender_records, fix_mx_certificate, renew_vmc_certificate, dkim_selector_not_imported, set_up_bimiWhy a done ticket closed. 'verified': Palisade's own check found the problem gone. 'manual': a person or an API caller marked it done and nothing was checked. Null on a ticket that is not done, and on one closed before the reason was first recorded. More values may be added, so treat an unknown one as unspecified.
verified, manualUpdate a task
/tasks/{id}requires authPath parameters
Headers
2025-04-30, unstableRequest body
open, snoozed, canceled, dismissed, pending, doneStops counting the ticket's sender against SPF on its domain. Ignoring both SPF and DKIM for the ticket's sender discards it, which answers the sender's confirm_source ticket: a confirm_source ticket updated so that both are ignored is closed as done unless the status sent is dismissed or canceled, and any other open confirm_source ticket for the same sender closes as well.
Stops counting the ticket's sender against DKIM on its domain. Ignoring both SPF and DKIM for the ticket's sender discards it, which answers the sender's confirm_source ticket: a confirm_source ticket updated so that both are ignored is closed as done unless the status sent is dismissed or canceled, and any other open confirm_source ticket for the same sender closes as well.
Confirms the ticket's sender for its domain. That answers the sender's confirm_source ticket, so a confirm_source ticket updated with this flag is closed as done unless the status sent is dismissed or canceled, and any other open confirm_source ticket for the same sender closes as well.
Example request
curl -X POST "https://api.palisade.email/tasks/<id>" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30" \
-H "Content-Type: application/json" \
-d '{
"status": "open",
"ignore_spf": true,
"ignore_dkim": true,
"confirm_source": true,
"confirm_source_in_use": true
}'
Responses
Success
Response body
Where the task sits in the email-authentication rollout, lower first: 10 DMARC setup, 20 foundation records, 30 SPF/DKIM alignment, 40 cleanup, 50 enforcement, 60 hardening. Separate from priority, which is urgency; sequence orders tasks of equal priority, since an alignment task cannot be worked before DMARC reporting exists to show the failure.
open, snoozed, canceled, dismissed, pending, donecleanup_spf_record, confirm_source, lockdown_domain, reduce_spf_lookups, set_up_dmarc_record, source_failing_dkim, source_failing_spf, set_up_mx_record, set_up_spf_record, update_dmarc_record, update_ttl, set_up_mta_sts, set_up_tls_rpt, resolve_dns_conflict, review_unused_sender, cleanup_sender_records, fix_mx_certificate, renew_vmc_certificate, dkim_selector_not_imported, set_up_bimiWhy a done ticket closed. 'verified': Palisade's own check found the problem gone. 'manual': a person or an API caller marked it done and nothing was checked. Null on a ticket that is not done, and on one closed before the reason was first recorded. More values may be added, so treat an unknown one as unspecified.
verified, manualOrganization
Create an organization
/organizationsrequires authHeaders
2025-04-30, unstableRequest body
3 · Max length: 128If provided, an invitation will be sent to this email to join the organization as an admin.
This field should be omitted or kept null when using an API key.
Self-serve plan to provision. Only honored when PLG is enabled; otherwise the default plan is used.
free, it_teams, mspOpaque first-party journey id carried from palisade.email. Ignored for non-self-serve creation.
Example request
curl -X POST "https://api.palisade.email/organizations" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30" \
-H "Content-Type: application/json" \
-d '{
"name": "string",
"invite_email": "user@example.com",
"referer": "string",
"pricing_type": "free",
"attribution_id": "5cf10a30-0b0c-4e05-9e68-6cbfd7d3c2a1"
}'
Responses
Success
Response body
Whether every member must complete multi-factor authentication to sign in to this organization. A member who has not set up an authenticator is asked to at their next sign-in.
properties
Email notification preferences for the organization. Controls which types of emails are sent.
properties
Send notifications when domain DNS records drift from expected configuration.
trueSend notifications when a domain fails DMARC validation checks.
trueSend notifications when a domain DMARC configuration is successfully set up.
trueSend daily digest of new and pending tasks.
trueSend reminders to finish adding and verifying a first domain.
trueSend an email when a newly set-up domain's first DMARC data arrives, and its first report a week later.
trueRemind invitees about an unaccepted invitation, and tell the inviter which invitations are about to expire.
trueSend plan-usage notices, such as passing the Free plan monthly email allowance.
trueSend a one-time email when a domain's Hosted SPF setup finishes and starts serving.
trueSend a notification when a domain never delegated to a record Palisade hosts for it, so the hosted record is not serving. Controlled separately from domain_drifted.
trueWhen someone dismissed or finished the onboarding wizard for this organization. Absent or null means nobody has, and the wizard is still offered to an organization with no domains.
palisade, sherwebPresent only when invite_email was given and the identity provider returned an error while creating that invitation. The organization itself was created. The message says whether the invitation was created anyway, was not created, or could not be checked; list the organization's invitations before inviting the address again, since a retry creates a second invitation.
OrganizationInvitationFailure
upstream_failureUpdate an organization
/organizations/{id}requires authPath parameters
Headers
2025-04-30, unstableRequest body
Whether or not the organization should be active.
3 · Max length: 128Organization contact email address.
Organization contact phone number.
1 · Max length: 50Organization website URL.
Organization settings including email notification preferences.
properties
Email notification preferences for the organization. Controls which types of emails are sent.
properties
Send notifications when domain DNS records drift from expected configuration.
trueSend notifications when a domain fails DMARC validation checks.
trueSend notifications when a domain DMARC configuration is successfully set up.
trueSend daily digest of new and pending tasks.
trueSend reminders to finish adding and verifying a first domain.
trueSend an email when a newly set-up domain's first DMARC data arrives, and its first report a week later.
trueRemind invitees about an unaccepted invitation, and tell the inviter which invitations are about to expire.
trueSend plan-usage notices, such as passing the Free plan monthly email allowance.
trueSend a one-time email when a domain's Hosted SPF setup finishes and starts serving.
trueSend a notification when a domain never delegated to a record Palisade hosts for it, so the hosted record is not serving. Controlled separately from domain_drifted.
trueRequire every member to complete multi-factor authentication at each sign-in. Only an administrator of this organization can change it, from a signed-in session rather than an API key, and changing it in either direction is refused with mfa_confirmation_required until that administrator's own sign-in has completed multi-factor authentication.
Example request
curl -X POST "https://api.palisade.email/organizations/<id>" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30" \
-H "Content-Type: application/json" \
-d '{
"is_active": true,
"name": "string",
"logo_url": "https://example.com",
"email": "user@example.com",
"phone_number": "string",
"website": "https://example.com",
"settings": {
"email_notifications": {
"domain_drifted": true,
"domain_failed": true,
"domain_setup": true,
"tasks_digests": true,
"setup_reminders": true,
"first_report": true,
"invitation_reminders": true,
"billing_notices": true,
"hosted_spf_live": true,
"delegation_missing": true
}
},
"require_mfa": true
}'
Responses
Success
Response body
Whether every member must complete multi-factor authentication to sign in to this organization. A member who has not set up an authenticator is asked to at their next sign-in.
properties
Email notification preferences for the organization. Controls which types of emails are sent.
properties
Send notifications when domain DNS records drift from expected configuration.
trueSend notifications when a domain fails DMARC validation checks.
trueSend notifications when a domain DMARC configuration is successfully set up.
trueSend daily digest of new and pending tasks.
trueSend reminders to finish adding and verifying a first domain.
trueSend an email when a newly set-up domain's first DMARC data arrives, and its first report a week later.
trueRemind invitees about an unaccepted invitation, and tell the inviter which invitations are about to expire.
trueSend plan-usage notices, such as passing the Free plan monthly email allowance.
trueSend a one-time email when a domain's Hosted SPF setup finishes and starts serving.
trueSend a notification when a domain never delegated to a record Palisade hosts for it, so the hosted record is not serving. Controlled separately from domain_drifted.
trueWhen someone dismissed or finished the onboarding wizard for this organization. Absent or null means nobody has, and the wizard is still offered to an organization with no domains.
palisade, sherwebDelete an organization
/organizations/{id}requires authPath parameters
Headers
2025-04-30, unstableExample request
curl -X DELETE "https://api.palisade.email/organizations/<id>" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Accepted
Response body
trueorganizationDismiss onboarding
/organizations/{id}/onboarding/dismissrequires authRecords that the onboarding wizard has been dismissed or finished, so it is not offered again. Idempotent: a second call keeps the first timestamp. Requires domains:read, the same permission that decides whether the wizard is shown.
Path parameters
Headers
2025-04-30, unstableExample request
curl -X POST "https://api.palisade.email/organizations/<id>/onboarding/dismiss" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
Whether every member must complete multi-factor authentication to sign in to this organization. A member who has not set up an authenticator is asked to at their next sign-in.
properties
Email notification preferences for the organization. Controls which types of emails are sent.
properties
Send notifications when domain DNS records drift from expected configuration.
trueSend notifications when a domain fails DMARC validation checks.
trueSend notifications when a domain DMARC configuration is successfully set up.
trueSend daily digest of new and pending tasks.
trueSend reminders to finish adding and verifying a first domain.
trueSend an email when a newly set-up domain's first DMARC data arrives, and its first report a week later.
trueRemind invitees about an unaccepted invitation, and tell the inviter which invitations are about to expire.
trueSend plan-usage notices, such as passing the Free plan monthly email allowance.
trueSend a one-time email when a domain's Hosted SPF setup finishes and starts serving.
trueSend a notification when a domain never delegated to a record Palisade hosts for it, so the hosted record is not serving. Controlled separately from domain_drifted.
trueWhen someone dismissed or finished the onboarding wizard for this organization. Absent or null means nobody has, and the wizard is still offered to an organization with no domains.
palisade, sherwebUsage
Get domain usage counts
/usagerequires authQuery parameters
domains, organizations, line_items, aligned_messagesHeaders
2025-04-30, unstableExample request
curl "https://api.palisade.email/usage" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
items
items
LineItem
DOMAIN-ACTIVE-TRIAL, DOMAIN-ACTIVE-FREE, DOMAIN-ACTIVE-1TO10, DOMAIN-ACTIVE-11TO100, DOMAIN-ACTIVE-101TO1000, DOMAIN-ACTIVE-1001PLUS, DOMAIN-INACTIVE, DOMAIN-PARKED, AGENT-ADDONLineItem
DOMAIN-ACTIVE-TRIAL, DOMAIN-ACTIVE-FREE, DOMAIN-ACTIVE-1TO10, DOMAIN-ACTIVE-11TO100, DOMAIN-ACTIVE-101TO1000, DOMAIN-ACTIVE-1001PLUS, DOMAIN-INACTIVE, DOMAIN-PARKED, AGENT-ADDONHow many messages authenticated as the organization's own mail (SPF- or DKIM-aligned) were reported over the requested range, across the organization and any active children. This is the volume an IT teams tier is sold against. Returned only when requested through expand, since it aggregates the DMARC report table.
0Member
List organization members
/membersrequires authHeaders
2025-04-30, unstableExample request
curl "https://api.palisade.email/members" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
Member
email_password, google, microsoftMemberRole
admin, editor, viewerproperties
Add an existing account
/membersrequires authAdds an existing Palisade account to your organization. Use this when the person already has an account: POST /invitations sends them to a signup screen they cannot complete, and returns invitation_invitee_exists for such an address. Returns 201 when the account is added and 200 when it was already a member, in which case the requested roles and groups are still applied.
Headers
2025-04-30, unstableRequest body
Email address of an existing Palisade account. Use POST /invitations for someone who has no account yet.
MemberRole
admin, editor, viewerExample request
curl -X POST "https://api.palisade.email/members" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30" \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"roles": [
"admin"
],
"groups": [
"5cf10a30-0b0c-4e05-9e68-6cbfd7d3c2a1"
]
}'
Responses
Already a member; roles and groups applied
Response body
email_password, google, microsoftMemberRole
admin, editor, viewerAdded
Response body
email_password, google, microsoftMemberRole
admin, editor, viewerNo Palisade account exists for this email address. Send an invitation instead.
Response body
parameter_invalid_or_missingemailUpdate a member
/members/{id}requires authPath parameters
Headers
2025-04-30, unstableRequest body
MemberRole
admin, editor, viewerExample request
curl -X POST "https://api.palisade.email/members/<id>" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30" \
-H "Content-Type: application/json" \
-d '{
"roles": [
"admin"
],
"groups": [
"5cf10a30-0b0c-4e05-9e68-6cbfd7d3c2a1"
]
}'
Responses
Success
Response body
email_password, google, microsoftMemberRole
admin, editor, viewerRemove a member
/members/{id}requires authPath parameters
Headers
2025-04-30, unstableExample request
curl -X DELETE "https://api.palisade.email/members/<id>" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Deleted
Response body
List member MFA statuses
/members/mfa/statusesrequires authHeaders
2025-04-30, unstableExample request
curl "https://api.palisade.email/members/mfa/statuses" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
MtaSts
Get MTA-STS status
/domains/{domainId}/mta-stsrequires authPath parameters
Headers
2025-04-30, unstableExample request
curl "https://api.palisade.email/domains/<domainId>/mta-sts" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
testing, enforce, noneEnable MTA-STS
/domains/{domainId}/mta-stsrequires authPath parameters
Headers
2025-04-30, unstableRequest body
testing, enforce, none · Default: "testing"86400 · Min: 86400 · Max: 31557600Example request
curl -X POST "https://api.palisade.email/domains/<domainId>/mta-sts" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30" \
-H "Content-Type: application/json" \
-d '{}'
Responses
Success
Response body
testing, enforce, noneUpdate the MTA-STS policy
/domains/{domainId}/mta-stsrequires authPath parameters
Headers
2025-04-30, unstableRequest body
testing, enforce, none86400 · Max: 31557600Example request
curl -X PUT "https://api.palisade.email/domains/<domainId>/mta-sts" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30" \
-H "Content-Type: application/json" \
-d '{
"mode": "testing",
"max_age": 86400
}'
Responses
Success
Response body
testing, enforce, noneDisable MTA-STS
/domains/{domainId}/mta-stsrequires authPath parameters
Headers
2025-04-30, unstableExample request
curl -X DELETE "https://api.palisade.email/domains/<domainId>/mta-sts" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
testing, enforce, noneRetry a failed MTA-STS setup
/domains/{domainId}/mta-sts/retryrequires authRequests a fresh certificate for mta-sts.{domain} after a failed setup. The domain must already have MTA-STS hosting enabled, must currently be in the error state, and must be publishing the mta-sts CNAME, otherwise the retry is refused with an explanation. A setup still in progress is refused rather than restarted. Returns the domain unchanged when its certificate is already active.
Path parameters
Headers
2025-04-30, unstableExample request
curl -X POST "https://api.palisade.email/domains/<domainId>/mta-sts/retry" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
testing, enforce, noneReport Data
Get the report summary
/report-data/summaryrequires authQuery parameters
last_1_day, last_7_days, last_30_days, last_365_daysHeaders
2025-04-30, unstableExample request
curl "https://api.palisade.email/report-data/summary" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
ReportSenderVolume
List domain report scores
/report-data/domainsrequires authQuery parameters
last_1_day, last_7_days, last_30_days, last_365_daysHeaders
2025-04-30, unstableExample request
curl "https://api.palisade.email/report-data/domains" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
ReportDomain
critical, bad, good, greatproperties
List senders for a domain
/report-data/domains/{domainId}/sendersrequires authPath parameters
Query parameters
last_1_day, last_7_days, last_30_days, last_365_daysHeaders
2025-04-30, unstableExample request
curl "https://api.palisade.email/report-data/domains/<domainId>/senders" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
ReportSenderAggregate
Get daily volume
/report-data/domains/{domainId}/timeseriesrequires authPath parameters
Query parameters
last_1_day, last_7_days, last_30_days, last_365_daysHeaders
2025-04-30, unstableExample request
curl "https://api.palisade.email/report-data/domains/<domainId>/timeseries" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
ReportTimeseriesPoint
Prospecting Reports
Download the hosted PDF
/prospecting-reports/{id}/downloadServes the report to anyone holding the link — no authentication, since the recipient is a prospect. Reports are available for 90 days from creation; after that this returns 410 with a page explaining that the report expired, or the JSON below when the request asks for it.
Path parameters
Example request
curl "https://api.palisade.email/prospecting-reports/<id>/download"
Responses
The report as a PDF
Response body
The report has expired and is no longer available
Response body
prospecting_report_expiredList prospecting reports
/prospecting-reportsrequires authProspecting reports created through this API, newest first. API keys see every one in the organization. A member limited to groups sees only the reports they created and the reports whose domains are all monitored domains in their groups.
Query parameters
Headers
2025-04-30, unstableExample request
curl "https://api.palisade.email/prospecting-reports" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
ProspectingReport
1en, fr1The skin the report is drawn in: light on paper, or dark on a near-black ground.
light, darkThe currency every price band in the report is printed in.
USD, CAD, EUR, GBP, AUDHow many weeks the plan and closing pages give the reader to fix what the report found.
1 · Max: 52properties
Generate a prospecting report
/prospecting-reportsrequires authAudits each domain against live DNS, renders the email security report as a PDF, and hosts it. The domains are looked up publicly and do not need to be in your account, which is what makes this usable on a prospect. Up to 10 domains per report. The response carries a url anyone with the link can open, good for 90 days; delete the report to stop it resolving sooner.
Headers
2025-04-30, unstableRequest body
1en, fr · Default: "en"truetruefalsetrueThe skin the report is drawn in: light on paper, or dark on a near-black ground.
light, dark · Default: "light"The currency every price band in the report is printed in.
USD, CAD, EUR, GBP, AUD · Default: "USD"How many weeks the plan and closing pages give the reader to fix what the report found.
6 · Min: 1 · Max: 52Example request
curl -X POST "https://api.palisade.email/prospecting-reports" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30" \
-H "Content-Type: application/json" \
-d '{
"generated_for": "string",
"domains": [
"string"
],
"language": "en",
"include_organization_info": true,
"include_bimi": true,
"include_dns_records": false,
"include_potential_loss": true,
"theme": "light",
"currency": "USD",
"deadline_weeks": 6
}'
Responses
Created
Response body
1en, fr1The skin the report is drawn in: light on paper, or dark on a near-black ground.
light, darkThe currency every price band in the report is printed in.
USD, CAD, EUR, GBP, AUDHow many weeks the plan and closing pages give the reader to fix what the report found.
1 · Max: 52Preview a report
/prospecting-reports/previewrequires authRuns the same audit as POST /prospecting-reports and returns the report itself rather than a link to a hosted PDF. format: "json" returns the report as data -- every score, finding and figure the PDF prints, with the wording resolved for the requested language -- so you can render it in your own layout. format: "html" returns the same report as a complete, self-contained HTML document, styled by Palisade and carrying your organization's name, logo and contact details. Nothing is stored and no link is minted, so use this for a page rendered on demand and POST /prospecting-reports when the recipient needs a PDF they can keep.
Headers
2025-04-30, unstableRequest body
1en, fr · Default: "en"truetruefalsetrueThe skin the report is drawn in: light on paper, or dark on a near-black ground.
light, dark · Default: "light"The currency every price band in the report is printed in.
USD, CAD, EUR, GBP, AUD · Default: "USD"How many weeks the plan and closing pages give the reader to fix what the report found.
6 · Min: 1 · Max: 52json returns the report as data; html returns the same report as a complete, self-contained HTML document.
json, html · Default: "json"Example request
curl -X POST "https://api.palisade.email/prospecting-reports/preview" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30" \
-H "Content-Type: application/json" \
-d '{
"generated_for": "string",
"domains": [
"string"
],
"language": "en",
"include_organization_info": true,
"include_bimi": true,
"include_dns_records": false,
"include_potential_loss": true,
"theme": "light",
"currency": "USD",
"deadline_weeks": 6,
"format": "json"
}'
Responses
The report as data, or as an HTML document when format is "html"
Response body
en, frThe skin the report is drawn in: light on paper, or dark on a near-black ground.
light, darkThe currency every price band in the report is printed in.
USD, CAD, EUR, GBP, AUDHow many weeks the plan and closing pages give the reader to fix what the report found.
1 · Max: 52Your organization name, as the report signs itself.
properties
properties
ProspectingReportCover
The generated date as the report prints it, in the requested language.
one, some, all, partial_one, partial, noneWorst score first, capped at the number of rows the cover prints.
ProspectingReportCoverRow
critical, bad, good, greatcritical, high, medium, lowHow many of the domain's checks are issues rather than passes.
properties
pass, fail, soft-warn, infoSet when the report holds more domains than the cover lists.
ProspectingReportDomain
critical, bad, good, greatcritical, high, medium, lowDeprecated. A value read off a fixed curve, not a comparison with the scores of other domains, so it does not say how this domain ranks. The report stopped printing it for that reason; it is kept only so existing callers do not break. Do not show it to a reader as a ranking.
properties
none, quarantine, reject, or unknown when the domain publishes no DMARC record.
high, medium, low, unknownTrue only at reject with pct=100.
ProspectingReportRiskSummary
properties
properties
properties
Every check, including the ones that pass.
ProspectingReportFinding
Which check this is: mx, spf, dmarc, bimi.
pass, warn, fail or error.
The risk word the report prints for this status, in language.
security or deliverability.
The finding as the report states it, in language.
Null when include_potential_loss is false.
ProspectingReportPotentialLoss
The figure as the report prints it, which floors a perfect score at "<10%".
The records as published. Null unless include_dns_records is true.
properties
The services the domain's SPF record authorises to send as it. Empty when it publishes none.
items
The catalogue's name for the service, or the SPF host itself when the catalogue has no entry.
The host as it stands in the domain's own SPF record.
Whether a DKIM key for this service was found on the domain. unknown when the service publishes per-customer selectors, which cannot be enumerated, or when it publishes none the check knows.
signed, missing, unknownWhat kind of mail the service carries for the domain, from the curated catalogue. Null when unknown.
invoices, marketing, sales, support, notifications, transactional, payroll, mailbox, security-gateway, relayDomains whose nameservers returned nothing usable, so the report has no page for them.
Get a prospecting report
/prospecting-reports/{id}requires authPath parameters
Headers
2025-04-30, unstableExample request
curl "https://api.palisade.email/prospecting-reports/<id>" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
1en, fr1The skin the report is drawn in: light on paper, or dark on a near-black ground.
light, darkThe currency every price band in the report is printed in.
USD, CAD, EUR, GBP, AUDHow many weeks the plan and closing pages give the reader to fix what the report found.
1 · Max: 52Delete a prospecting report
/prospecting-reports/{id}requires authDeletes the report and the hosted PDF, so any link already sent out stops resolving.
Path parameters
Headers
2025-04-30, unstableExample request
curl -X DELETE "https://api.palisade.email/prospecting-reports/<id>" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
Scheduled Reports
List scheduled reports
/scheduled-reportsrequires authQuery parameters
Headers
2025-04-30, unstableExample request
curl "https://api.palisade.email/scheduled-reports" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
ScheduledReport
11[]1properties
Create a scheduled report
/scheduled-reportsrequires authHeaders
2025-04-30, unstableRequest body
1"0 0 1 * *" · Min length: 1false[]Example request
curl -X POST "https://api.palisade.email/scheduled-reports" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30" \
-H "Content-Type: application/json" \
-d '{
"customer_name": "string",
"domain_ids": [
"5cf10a30-0b0c-4e05-9e68-6cbfd7d3c2a1"
],
"schedule_frequency": "0 0 1 * *",
"auto_send": false,
"email_recipients": []
}'
Responses
Success
Response body
11[]1Get a scheduled report
/scheduled-reports/{id}requires authPath parameters
Headers
2025-04-30, unstableExample request
curl "https://api.palisade.email/scheduled-reports/<id>" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
11[]1Update a scheduled report
/scheduled-reports/{id}requires authPath parameters
Headers
2025-04-30, unstableRequest body
11Example request
curl -X POST "https://api.palisade.email/scheduled-reports/<id>" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30" \
-H "Content-Type: application/json" \
-d '{
"customer_name": "string",
"domain_ids": [
"5cf10a30-0b0c-4e05-9e68-6cbfd7d3c2a1"
],
"schedule_frequency": "string",
"auto_send": true,
"email_recipients": [
"user@example.com"
],
"generated_at": "2025-01-15T12:00:00.000Z"
}'
Responses
Success
Response body
11[]1Delete a scheduled report
/scheduled-reports/{id}requires authPath parameters
Headers
2025-04-30, unstableExample request
curl -X DELETE "https://api.palisade.email/scheduled-reports/<id>" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Deleted
Response body
SupportRequest
Send a support request
/support-requestsrequires authHeaders
2025-04-30, unstableRequest body
1 · Max length: 40001 · Max length: 100Example request
curl -X POST "https://api.palisade.email/support-requests" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30" \
-H "Content-Type: application/json" \
-d '{
"content": "string",
"title": "string"
}'
Responses
Success
Response body
createdSupportTicket
List support tickets
/support/ticketsrequires authReturns paginated list of support tickets. Admins see all org tickets; other roles see only their own tickets. Filter by status or priority using query params.
Query parameters
open, pending_customer, pending_support, resolved, closedlow, normal, high, urgent, criticalHeaders
2025-04-30, unstableExample request
curl "https://api.palisade.email/support/tickets" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
SupportTicket
open, pending_customer, pending_support, resolved, closedlow, normal, high, urgent, criticalproperties
Open a support ticket
/support/ticketsrequires authCreates a new support ticket with an initial message. Optionally link to a hostname or task. Returns the created ticket ID.
Headers
2025-04-30, unstableRequest body
1 · Max length: 2551items
file, linkExample request
curl -X POST "https://api.palisade.email/support/tickets" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30" \
-H "Content-Type: application/json" \
-d '{
"subject": "string",
"content": "string",
"priority": {},
"hostname_id": "5cf10a30-0b0c-4e05-9e68-6cbfd7d3c2a1",
"attachments": [
{
"file_name": "string",
"file_url": "https://example.com",
"file_size": 0,
"mime_type": "string",
"attachment_type": "file"
}
]
}'
Responses
Created
Response body
properties
Get a support ticket
/support/tickets/{id}requires authReturns a single ticket with its full message thread. Messages are ordered chronologically. Marks all support messages as read for the requesting user.
Path parameters
Headers
2025-04-30, unstableExample request
curl "https://api.palisade.email/support/tickets/<id>" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
open, pending_customer, pending_support, resolved, closedlow, normal, high, urgent, criticalSupportTicketMessage
customer, support, systemSupportTicketAttachment
Download URL for the attachment. For uploaded files this is a signed URL minted for this response and valid for one hour; fetch the ticket again for a fresh one rather than storing it. For link attachments it is the URL as supplied.
file, linkClose or reopen a ticket
/support/tickets/{id}requires authUpdates ticket status. Users can close a resolved ticket or reopen a closed/resolved ticket.
Path parameters
Headers
2025-04-30, unstableRequest body
open, closedExample request
curl -X PATCH "https://api.palisade.email/support/tickets/<id>" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30" \
-H "Content-Type: application/json" \
-d '{
"status": "open"
}'
Responses
Success
Response body
open, pending_customer, pending_support, resolved, closedReply to a ticket
/support/tickets/{id}/messagesrequires authAdds a reply message to an existing ticket. Updates ticket status to PENDING_SUPPORT.
Path parameters
Headers
2025-04-30, unstableRequest body
1items
file, linkExample request
curl -X POST "https://api.palisade.email/support/tickets/<id>/messages" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30" \
-H "Content-Type: application/json" \
-d '{
"content": "string",
"attachments": [
{
"file_name": "string",
"file_url": "https://example.com",
"file_size": 0,
"mime_type": "string",
"attachment_type": "file"
}
]
}'
Responses
Created
Response body
Get the unread count
/support/unread-countrequires authReturns the count of unread support messages across visible tickets. Lightweight query for badge polling.
Headers
2025-04-30, unstableExample request
curl "https://api.palisade.email/support/unread-count" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
Get an attachment upload URL
/support/presigned-urlrequires authGenerates a presigned URL for uploading support ticket attachments to S3. Supports images and PDFs up to 10MB.
Headers
2025-04-30, unstableRequest body
1 · Max length: 255image/png, image/jpeg, image/gif, image/webp, application/pdfExample request
curl -X POST "https://api.palisade.email/support/presigned-url" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30" \
-H "Content-Type: application/json" \
-d '{
"file_name": "string",
"mime_type": "image/png"
}'
Responses
Success
Response body
TlsReport
List TLS-RPT reports
/domains/{domainId}/tls-reportsrequires authList the TLS-RPT reports sending servers have submitted for this domain. Reports only arrive once the domain publishes an MTA-STS policy and a TLS-RPT record.
Path parameters
Query parameters
day, total_successful, total_failure, organization_namedesc, ascHeaders
2025-04-30, unstableExample request
curl "https://api.palisade.email/domains/<domainId>/tls-reports" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
items
items
properties
Get daily TLS session counts
/domains/{domainId}/tls-reports/chartrequires authSuccessful and failed TLS session counts per day over the requested window, as parallel arrays aligned to labels.
Path parameters
Query parameters
Headers
2025-04-30, unstableExample request
curl "https://api.palisade.email/domains/<domainId>/tls-reports/chart" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
properties
Get the TLS-RPT summary
/domains/{domainId}/tls-reports/summaryrequires authAggregate TLS session totals for the requested window, with failures broken down by RFC 8460 result type.
Path parameters
Query parameters
Headers
2025-04-30, unstableExample request
curl "https://api.palisade.email/domains/<domainId>/tls-reports/summary" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
items
Get a TLS-RPT report
/domains/{domainId}/tls-reports/{id}requires authRetrieve a single TLS-RPT report, including the per-failure detail sending servers reported.
Path parameters
Headers
2025-04-30, unstableExample request
curl "https://api.palisade.email/domains/<domainId>/tls-reports/<id>" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
items
Activity Log
List activity log entries
/activity-logrequires authQuery parameters
Headers
2025-04-30, unstableExample request
curl "https://api.palisade.email/activity-log" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
ActivityLogEntry
USER, API_KEY, PALISADE_STAFF, SYSTEMproperties
List action types
/activity-log/actionsrequires authHeaders
2025-04-30, unstableExample request
curl "https://api.palisade.email/activity-log/actions" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
Get an activity log entry
/activity-log/{id}requires authPath parameters
Headers
2025-04-30, unstableExample request
curl "https://api.palisade.email/activity-log/<id>" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
USER, API_KEY, PALISADE_STAFF, SYSTEMSignup
Start a headless signup
/signupStart a headless signup: sends a 6-digit verification code to the given work email. No account is created until the code is verified.
Request body
Email address that will own the new account. A verification code is sent to this inbox; the address becomes the organization admin.
3 · Max length: 128Self-serve plan to provision. Only honored when PLG is enabled; otherwise the default plan is used.
free, it_teams, mspOpaque first-party journey id from palisade.email. Used only for acquisition attribution.
Example request
curl -X POST "https://api.palisade.email/signup" \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"organization_name": "string",
"pricing_type": "free",
"attribution_id": "5cf10a30-0b0c-4e05-9e68-6cbfd7d3c2a1"
}'
Responses
Verification code sent
Response body
Verify a signup code
/signup/verifyVerify the emailed code. On success, creates the Auth0 user (email verified), the organization, and returns an org-scoped API key exactly once.
Request body
Example request
curl -X POST "https://api.palisade.email/signup/verify" \
-H "Content-Type: application/json" \
-d '{
"signup_id": "5cf10a30-0b0c-4e05-9e68-6cbfd7d3c2a1",
"code": "string"
}'
Responses
Account created
Response body
Org-scoped API key. Shown exactly once — store it securely.
Source
List sending sources
/sourcesrequires authList the sending sources Palisade knows about, with the SPF and DKIM support details used to build setup instructions. Authentication is optional. instructions_curation holds unreviewed AI proposals and is null unless the caller holds sources:update.
Query parameters
ACTIVE, PENDING_REVIEW, REJECTEDDMARC_IO, AI_DISCOVERED, MANUALExample request
curl "https://api.palisade.email/sources" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
items
SENDING_TOOL, MAILBOX_PROVIDER, VPS_PROVIDER, SECURITY_PROVIDER, EMAIL_RELAYNONE, RARE, FULLproperties
properties
properties
items
TXT, CNAME, MXNONE, RARE, FULLproperties
items
DIRECT, SUBDOMAIN, MANAGED_SUBDOMAINNOT_FORWARDER, FORWARDER, FORWARDER_ONLYproperties
items
TXT, CNAMEproperties
items
TXT, CNAME, MXproperties
properties
PENDING, APPROVED, REJECTEDproperties
items
TXT, CNAME, MXproperties
properties
PENDING, APPROVED, REJECTEDproperties
items
TXT, CNAME, MXproperties
ACTIVE, PENDING_REVIEW, REJECTEDDMARC_IO, AI_DISCOVERED, MANUALproperties
Get the SPF include index
/sources/spf-indexrequires authThe compact include-to-sender index used to name the mechanisms in an SPF record, and to offer senders to add. Only sources that carry at least one SPF value appear. values holds the mechanisms Palisade prescribes adding; recognition_values additionally holds observed values, which name a mechanism already present in a record but are not safe to publish on a user's behalf. Authentication is optional, as on the list endpoint.
Example request
curl "https://api.palisade.email/sources/spf-index" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
items
SPF mechanisms Palisade prescribes adding for this source. Safe to publish on a user's behalf.
Every mechanism that identifies this source, including values only observed in the wild. Use these to name a mechanism already present in a record; they are not safe to add to one.
When true, the mechanism depends on per-customer setup and must not be offered as a one-click add.
properties
Get the DKIM selector index
/sources/dkim-indexrequires authThe compact index used to name the DKIM keys already published for a domain. A key is matched either by selectors, the selector conventions a source publishes under, or by base_domains, the zones its CNAME targets sit in — the latter being the only signal that identifies a per-customer selector such as HubSpot's hs1-<portalId>. Only sources carrying at least one of the two appear. Authentication is optional, as on the list endpoint.
Example request
curl "https://api.palisade.email/sources/dkim-index" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
items
The source's home page. Free text on the record rather than a validated URL - a handful of sources carry a bare hostname such as samanage.com - so treat it as a hostname that may or may not carry a scheme.
DKIM selectors this source is known to publish under. Matched against the selector of a key already in DNS; they are per-source conventions, not values to publish on a customer's behalf.
Domains this source signs from. A DKIM CNAME whose target sits under one of these belongs to this source, which is the only signal that identifies a per-customer selector such as HubSpot's hs1-<portal>.
properties
Get a sending source
/sources/{id}requires authFetch a single sending source by id. Authentication is optional, and instructions_curation is redacted as on the list endpoint.
Path parameters
Example request
curl "https://api.palisade.email/sources/<id>" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
SENDING_TOOL, MAILBOX_PROVIDER, VPS_PROVIDER, SECURITY_PROVIDER, EMAIL_RELAYNONE, RARE, FULLproperties
properties
properties
items
TXT, CNAME, MXNONE, RARE, FULLproperties
items
DIRECT, SUBDOMAIN, MANAGED_SUBDOMAINNOT_FORWARDER, FORWARDER, FORWARDER_ONLYproperties
items
TXT, CNAMEproperties
items
TXT, CNAME, MXproperties
properties
PENDING, APPROVED, REJECTEDproperties
items
TXT, CNAME, MXproperties
properties
PENDING, APPROVED, REJECTEDproperties
items
TXT, CNAME, MXproperties
ACTIVE, PENDING_REVIEW, REJECTEDDMARC_IO, AI_DISCOVERED, MANUALSpf
Get SPF diagnostics
/domains/{domainId}/spfrequires authPath parameters
Headers
2025-04-30, unstableExample request
curl "https://api.palisade.email/domains/<domainId>/spf" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
Id of the domain the diagnostics are for.
The domain name whose live DNS was read, for example "example.com".
The SPF TXT record live DNS serves for the domain, or null when none is published. When more than one v=spf1 record exists they are joined with newlines here; see records for them individually.
Every v=spf1 TXT record found at the domain. More than one entry is itself an error — receivers treat it as a permanent failure.
TTL of the SPF TXT record in seconds, when it could be read.
Overall SPF health: "pass", "warn" or "fail".
DNS lookups the record costs receivers: every include, a, mx, ptr, exists and redirect term, counted recursively through every include and redirect. Terms receivers never reach are not charged: anything to the right of a matching all, and a redirect= in a record that also carries an all, which RFC 7208 section 6.1 says must be ignored.
The limit SPF imposes before receivers return a permanent error: 10.
How many more lookups the record could add before breaking. 0 when at or over the limit.
Every lookup in the chain, nested entries following their parent.
SpfLookup
The SPF term that costs the lookup: "include", "a", "mx", "ptr", "exists" or "redirect". "expanded-domain" marks a macro expansion, which costs none.
The operand the term queries, as published. Usually a hostname. A macro-bearing exists: carries the template here, and the substituted name follows as an expanded-domain entry when every macro in it could be resolved. A macro-bearing a:, mx: or ptr: carries the template here too, but is never expanded, so no expanded-domain entry follows it; only include: and redirect= operands are put through the macro resolver, and one whose macros all resolved reports the substituted name it queried here rather than the published template, under the note "macro-expanded" when that name publishes exactly one SPF record, and with error when it does not.
Nesting depth: 0 for mechanisms in the domain's own record, 1 for those inside an include it references, and so on.
DNS lookups this entry accounts for: itself plus everything nested under it. The expensive includes are the ones with the highest number here.
True when this lookup failed to resolve to a usable record.
Extra context, such as "loop", "unresolved", or one of "macro-expanded" / "macro-unexpanded". Any term whose operand carries a macro -- exists:, include: or redirect= -- carries one of those two, and costs one lookup either way, except that an expanded include: or redirect= carries no macro note once its target disappoints: "unresolved" when the lookup could not be completed, "loop" when it refers back, "no-txt" alongside error when the target returned no TXT records at all, and no note at all -- just error -- when the target returned TXT records but not a single SPF record among them.
Problems found, errors before warnings. Empty when SPF is healthy.
SpfProblem
Stable identifier for the problem, safe to branch on — for example "spf-max-10-lookups", "spf-multiple-records", "spf-lookup-failed" or "spf-no-record".
"error" when receivers fail SPF (or get no protection from it) because of this; "warning" for a risk that does not break evaluation.
error, warningThe hostname the problem is about, when it concerns a specific lookup.
What is wrong and what it means for mail, in plain language.
State of Palisade-hosted SPF for the domain. When managed, the domain publishes a single Palisade include and Palisade keeps the flattened chain under the 10-lookup limit.
properties
True when Palisade hosts and flattens the SPF record for this domain.
Live status of the hosted SPF chain, when managed.
The record Palisade flattens and publishes, when hosted SPF is configured.
Why managed_dns_status.bimi is "error". "setup_timeout" means the customer CNAME was never detected within the verification window (setup was never completed); "drift" means a previously verified CNAME stopped pointing at Palisade; "record_conflict" means default._bimi holds conflicting records — see dns_conflicts. Null when there is no error or the error predates reason tracking.
When Palisade last flattened and published the hosted chain, ISO 8601.
The single action Palisade suggests taking next.
Tool
Audit a domain
/tools/auditrequires authRun the full email-authentication audit against a domain from live DNS: MX, SPF, DKIM, DMARC, BIMI, MTA-STS and TLS-RPT, each scored and annotated, plus an overall score out of 100. The domain does not have to be one you have added to Palisade. Results are cached for ten minutes per domain. Authentication is optional. Note that this response predates the API-wide snake_case convention and keeps its original camelCase field names (mtaSts, lookupCount, dmarcValue), so it does not read like the rest of the API.
Query parameters
true, falsetrue, falsetrue, falseHeaders
The website visitor journey this audit belongs to, the same id sent to POST /attribution/touches. Read only when the request captures a lead, and ignored rather than rejected when it is missing or malformed.
Example request
curl "https://api.palisade.email/tools/audit" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
"success", or "error" when the audit could not run because the domain's nameservers did not resolve or belong to a domain-parking advertiser. On "error" only summary is present, with the reason in summary.errors.
success, errorThe headline: the overall score and one verdict per dimension.
properties
The domain audited, as requested.
The email query parameter, echoed back. Empty when none was sent, and empty on the error status whether or not one was.
True when Palisade has the domain on record as parked. A parked domain should send no mail, so only SPF and DMARC count toward its score.
0-100: 100 less what each counted dimension loses, as each dimension's score reports.
The MX verdict, the same value as mx.status.
The SPF verdict, the same value as spf.status.
The DKIM verdict, the same value as dkim.status.
The DMARC verdict, the same value as dmarc.status.
The BIMI verdict, the same value as bimi.status.
The MTA-STS verdict, the same value as mtaSts.status.
The TLS-RPT verdict, the same value as tlsRpt.status.
Why the audit could not run: "ns-error" when the nameservers did not resolve, "ns-for-advertising-domain" when they belong to a domain-parking advertiser. Empty on success.
Always empty. Findings are reported on each dimension.
Always empty. Findings are reported on each dimension.
The NS records the audit resolved: the domain's own, or its parent's when it has none.
The MX check.
properties
Points this dimension takes off the overall score: 0 at full marks, negative otherwise. Only MX, SPF, DKIM, DMARC and BIMI are counted, and only SPF and DMARC when the domain is parked.
Verdict: "pass", "warn" or "fail"; "in progress" for a DMARC policy short of full reject or MTA-STS in testing mode; "info" when optional MTA-STS or TLS-RPT is not set up. DKIM reports "error" when the catalogue of sending services Palisade probes was unavailable, so no selector was probed and the result says nothing about the domain.
What was found that is not a problem, such as "spf-success". MTA-STS and TLS-RPT write sentences instead of codes.
Problems that break or undermine the mechanism, as stable codes such as "spf-no-record". A host can follow a colon, as in "spf-lookup-failed:spf.example.com". MTA-STS and TLS-RPT write sentences instead of codes.
Risks worth fixing that do not break the mechanism, such as "spf-low-ttl". MTA-STS and TLS-RPT write sentences instead of codes.
The MX check as a state: "mx-present" or "mx-missing".
properties
The verdict this state carries: "pass", "warn", "fail", "in progress" or "info".
Stable identifier for what was found, safe to branch on. The field holding this object lists its values.
Points this state earns toward its dimension. Unlike the dimension's own score, it counts up from 0.
Codes for lesser problems found alongside the state, such as "spf-ptr-unrecommended". Usually empty.
The name the MX records were read from: the audited domain, or for a subdomain with no nameservers of its own, the parent whose nameservers answered.
The MX records found, most preferred first.
items
The mail server hostname.
MX preference. Lower values are tried first.
True when the MX lookup itself failed, so an empty mxValue is not evidence of absence.
The SPF check, including what the record costs in DNS lookups.
properties
Points this dimension takes off the overall score: 0 at full marks, negative otherwise. Only MX, SPF, DKIM, DMARC and BIMI are counted, and only SPF and DMARC when the domain is parked.
Verdict: "pass", "warn" or "fail"; "in progress" for a DMARC policy short of full reject or MTA-STS in testing mode; "info" when optional MTA-STS or TLS-RPT is not set up. DKIM reports "error" when the catalogue of sending services Palisade probes was unavailable, so no selector was probed and the result says nothing about the domain.
What was found that is not a problem, such as "spf-success". MTA-STS and TLS-RPT write sentences instead of codes.
Problems that break or undermine the mechanism, as stable codes such as "spf-no-record". A host can follow a colon, as in "spf-lookup-failed:spf.example.com". MTA-STS and TLS-RPT write sentences instead of codes.
Risks worth fixing that do not break the mechanism, such as "spf-low-ttl". MTA-STS and TLS-RPT write sentences instead of codes.
The SPF record as a state, such as "spf-soft-fail" (ends in ~all), "spf-closed" (ends in -all), "spf-missing", "spf-multiple-records" or "spf-invalid".
properties
The verdict this state carries: "pass", "warn", "fail", "in progress" or "info".
Stable identifier for what was found, safe to branch on. The field holding this object lists its values.
Points this state earns toward its dimension. Unlike the dimension's own score, it counts up from 0.
Codes for lesser problems found alongside the state, such as "spf-ptr-unrecommended". Usually empty.
The SPF record evaluated: the redirect target's when the domain uses redirect= and that target publishes exactly one record, otherwise the domain's own; every record joined by newlines, longest first, when more than one is published. Empty only when no record was found, a deprecated record type is published, or the domain publishes a single record carrying redirect= alongside an all mechanism - a record that loops, over-runs the lookup limit or has an unresolved include is still reported here.
DNS lookups counted from every term RFC 7208 section 4.6.4 charges one for -- include, a, mx, ptr, exists and redirect -- whether or not each one resolved, and whatever qualifier it carries. Over 10 is an SPF permerror. Each term counts once and names the host it queries, includes and redirects are followed recursively wherever they appear, and ip4, ip6 and all cost nothing. Two terms are deliberately not charged, because receivers never query them: anything standing to the right of a matching all, and a redirect= in a record that also carries an all, which RFC 7208 section 6.1 says must be ignored.
The DNS lookups the record costs receivers, as a tree: an include or redirect lists what it expands into under nested.
items
The term that costs the lookup: "include", "redirect", "a", "mx", "ptr" or "exists". "expanded-domain" is the name an exists: macro expands to, which costs no lookup.
The operand the term queries, as published rather than resolved -- with one exception: an include: or redirect= whose macros all resolved reports the substituted name it queried, under the note "macro-expanded" when that name publishes exactly one SPF record, and with error when it does not. A bare a, mx or ptr names the domain whose record it stands in, since that is what it queries: the audited domain at the top level, and the included or redirect target inside the subtree belonging to it. Two cases are not a hostname: an exists: carrying a macro is the template, and a nested expanded-domain node carries the substituted name only when %{i}, %{ir}, %{v} and %{d} are the only macros it uses -- any other macro form leaves the term unexpanded, carrying the note "macro-unexpanded" and no nested node; and an a:, mx: or ptr: carrying a macro, such as a:%{d}, is the template unexpanded, since only include: and redirect= operands are put through the macro resolver. A qualifier does not change the operand: ~a:mail.example.com and -mx:relay.example.net name the host each points at, exactly as the unqualified forms do.
The lookups this one expands into, each an SpfLookupNode.
"loop" for an include or redirect that refers back to a record already being evaluated, "unresolved" when the lookup could not be completed, "macro-expanded" for a term whose operand carried a macro that was substituted, and "macro-unexpanded" for one carrying a macro that cannot be resolved without a live sender. exists:, include: and redirect= can all carry either, and cost one lookup whichever it is -- except that an expanded include: or redirect= carries no macro note once its target disappoints: "unresolved" when the lookup could not be completed, "loop" when it refers back, "no-txt" alongside error when the target returned no TXT records at all, and no note at all -- just error -- when the target returned TXT records but not a single SPF record among them. An expanded exists: puts the substituted name in a nested expanded-domain node; an expanded include: or redirect= queries the substituted name and reports it as the value.
True when the include or redirect target publishes no single SPF record, or loops. A lookup that could not be completed carries the note "unresolved" and no error instead, and a target that returned no TXT records at all carries error together with the note "no-txt".
True when the SPF lookup itself failed, for the domain or its redirect= target, so what errors reports missing is not evidence of absence.
Always empty.
True when the domain still publishes the obsolete SPF record type (DNS type 99), which receivers ignore.
The ip4: ranges the record authorizes itself, not counting its includes. Empty when the record could not be evaluated.
The ip6: ranges the record authorizes itself, not counting its includes. Empty when the record could not be evaluated.
TTL of the SPF record in seconds, from the domain's authoritative nameservers. 0 or null when it could not be read.
Improvements worth making beyond errors and warnings, as codes such as "dmarc-policy-quarantine", which urges moving on to reject. Usually empty.
The DKIM check, over the selectors Palisade knows to probe.
properties
Points this dimension takes off the overall score: 0 at full marks, negative otherwise. Only MX, SPF, DKIM, DMARC and BIMI are counted, and only SPF and DMARC when the domain is parked.
Verdict: "pass", "warn" or "fail"; "in progress" for a DMARC policy short of full reject or MTA-STS in testing mode; "info" when optional MTA-STS or TLS-RPT is not set up. DKIM reports "error" when the catalogue of sending services Palisade probes was unavailable, so no selector was probed and the result says nothing about the domain.
What was found that is not a problem, such as "spf-success". MTA-STS and TLS-RPT write sentences instead of codes.
Problems that break or undermine the mechanism, as stable codes such as "spf-no-record". A host can follow a colon, as in "spf-lookup-failed:spf.example.com". MTA-STS and TLS-RPT write sentences instead of codes.
Risks worth fixing that do not break the mechanism, such as "spf-low-ttl". MTA-STS and TLS-RPT write sentences instead of codes.
The domain whose DKIM selectors were checked.
Every DKIM record found. Palisade probes only the selectors its catalogue of sending services uses, so a key under any other selector is not found: an empty list is not proof the domain has no DKIM.
items
The TXT record published at the selector.
The selector, published at <selector>._domainkey.<domain>.
The sending service in Palisade's catalogue that uses this selector.
The key type from k=, such as "rsa". Empty when the tag is absent, which means rsa.
The public key from p=. Empty when the key is revoked (p= with no value) or the tag is missing.
Points this record takes off the DKIM score. 0 when it is sound.
What was found that is not a problem, such as "spf-success". MTA-STS and TLS-RPT write sentences instead of codes.
Problems that break or undermine the mechanism, as stable codes such as "spf-no-record". A host can follow a colon, as in "spf-lookup-failed:spf.example.com". MTA-STS and TLS-RPT write sentences instead of codes.
Risks worth fixing that do not break the mechanism, such as "spf-low-ttl". MTA-STS and TLS-RPT write sentences instead of codes.
The DMARC check, which scores the policy and the reporting separately.
properties
The domain the DMARC record was read from: the audited domain, or the parent it was found on when the audited domain publishes none.
Points this dimension takes off the overall score: 0 at full marks, negative otherwise. Only MX, SPF, DKIM, DMARC and BIMI are counted, and only SPF and DMARC when the domain is parked.
Verdict: "pass", "warn" or "fail"; "in progress" for a DMARC policy short of full reject or MTA-STS in testing mode; "info" when optional MTA-STS or TLS-RPT is not set up. DKIM reports "error" when the catalogue of sending services Palisade probes was unavailable, so no selector was probed and the result says nothing about the domain.
What was found that is not a problem, such as "spf-success". MTA-STS and TLS-RPT write sentences instead of codes.
Problems that break or undermine the mechanism, as stable codes such as "spf-no-record". A host can follow a colon, as in "spf-lookup-failed:spf.example.com". MTA-STS and TLS-RPT write sentences instead of codes.
Risks worth fixing that do not break the mechanism, such as "spf-low-ttl". MTA-STS and TLS-RPT write sentences instead of codes.
Whether the record already sends aggregate reports to Palisade: "SETUP" if so, otherwise "NONE".
The policy half as a state: "dmarc-policy-none", "dmarc-policy-quarantine-*" or "dmarc-policy-reject-*" by pct= level (low, medium, high or full), "dmarc-missing" or "dmarc-invalid".
properties
The verdict this state carries: "pass", "warn", "fail", "in progress" or "info".
Stable identifier for what was found, safe to branch on. The field holding this object lists its values.
Points this state earns toward its dimension. Unlike the dimension's own score, it counts up from 0.
Codes for lesser problems found alongside the state, such as "spf-ptr-unrecommended". Usually empty.
The reporting half as a state: "dmarc-monitoring-managed" (aggregate reports reach Palisade), "dmarc-monitoring-external" (they go elsewhere), "dmarc-monitoring-missing" or "dmarc-monitoring-invalid".
properties
The verdict this state carries: "pass", "warn", "fail", "in progress" or "info".
Stable identifier for what was found, safe to branch on. The field holding this object lists its values.
Points this state earns toward its dimension. Unlike the dimension's own score, it counts up from 0.
Codes for lesser problems found alongside the state, such as "spf-ptr-unrecommended". Usually empty.
Every v=DMARC1 record found. More than one is an error: receivers then ignore DMARC.
The record evaluated. Null when none was found or more than one is published.
TTL of the DMARC record in seconds, from the authoritative nameservers. Null when it could not be read.
The tags the record sets, parsed. A tag it omits is null, or an empty list.
properties
The p= policy, lowercased: "none", "quarantine" or "reject".
The pct= percentage of failing mail the policy applies to. Null when absent, which means 100.
The fo= failure-reporting option: "0", "1", "d" or "s".
Where aggregate reports go: the rua= addresses, without mailto:.
Where failure reports go: the ruf= addresses, without mailto:.
The adkim= DKIM alignment mode: "r" relaxed or "s" strict. Null when absent, which means relaxed.
The aspf= SPF alignment mode: "r" relaxed or "s" strict. Null when absent, which means relaxed.
The sp= policy for subdomains. Null when absent, in which case subdomains take p=.
Reporting findings, kept apart from errors: codes such as "dmarc-missing-rua-tag", which means no aggregate reports are requested.
Improvements worth making beyond errors and warnings, as codes such as "dmarc-policy-quarantine", which urges moving on to reject. Usually empty.
True when the record is served through a CNAME rather than published directly.
True when that CNAME points at Palisade, which hosts the record.
True when the DMARC lookup itself failed, so what errors reports missing is not evidence of absence.
The BIMI check, including the logo and certificate the record links to.
properties
Points this dimension takes off the overall score: 0 at full marks, negative otherwise. Only MX, SPF, DKIM, DMARC and BIMI are counted, and only SPF and DMARC when the domain is parked.
Verdict: "pass", "warn" or "fail"; "in progress" for a DMARC policy short of full reject or MTA-STS in testing mode; "info" when optional MTA-STS or TLS-RPT is not set up. DKIM reports "error" when the catalogue of sending services Palisade probes was unavailable, so no selector was probed and the result says nothing about the domain.
What was found that is not a problem, such as "spf-success". MTA-STS and TLS-RPT write sentences instead of codes.
Problems that break or undermine the mechanism, as stable codes such as "spf-no-record". A host can follow a colon, as in "spf-lookup-failed:spf.example.com". MTA-STS and TLS-RPT write sentences instead of codes.
Risks worth fixing that do not break the mechanism, such as "spf-low-ttl". MTA-STS and TLS-RPT write sentences instead of codes.
The BIMI record as a state: "bimi-certified" (a logo and a certificate), "bimi-uncertified" (a logo without one), "bimi-missing", "bimi-invalid", "bimi-requirements-not-met" (DMARC is not at enforcement), or once the files are checked "bimi-logo-invalid", "bimi-vmc-invalid" or "bimi-vmc-expired".
properties
The verdict this state carries: "pass", "warn", "fail", "in progress" or "info".
Stable identifier for what was found, safe to branch on. The field holding this object lists its values.
Points this state earns toward its dimension. Unlike the dimension's own score, it counts up from 0.
Codes for lesser problems found alongside the state, such as "spf-ptr-unrecommended". Usually empty.
The record at default._bimi.<domain>. Null when none, or more than one, is published.
The logo URL from l=. Null when the tag is absent.
The a= value as published, kept verbatim: an https:// .pem URL where the tag carries one, otherwise the literal "self", an empty string, or whatever unusable value was set. A usable URL here is not a verdict on the certificate, because it is not cleared when the record later fails its checks - read bimiCertified for that. Null when the tag is absent or was not reached.
Improvements worth making beyond errors and warnings, as codes such as "dmarc-policy-quarantine", which urges moving on to reject. Usually empty.
When the certificate expires, taken from its validTo. Present when validation read a validTo, or when a cached expiry from an earlier read was reused; absent when the certificate could not be fetched or parsed, even though it was reached.
True when the record is served through a CNAME rather than published directly.
True when that CNAME points at Palisade, which hosts the record.
True when this audit attempted deep validation: fetching the logo, and the certificate when a= names one. It is set before those fetches run, so it does not mean either succeeded - read logoValidation and vmcValidation for that. Absent when the record failed before that step, and when a VMC result checked within the last 24 hours was reused instead of re-reading it.
What fetching and checking the logo at location found. Present when deepValidated is true.
properties
True when the logo could be downloaded.
True when it passed Palisade's checks for a BIMI SVG.
Why the logo failed, when it did.
What fetching and checking the certificate at assertion found. Present when deepValidated is true and a= names a certificate.
properties
True when the certificate file could be downloaded.
True when every certificate check passed. Warnings such as a logo mismatch do not count against it.
PEM certificates in the file.
True when the file carries every certificate from the leaf up to a self-signed root. Null until checked.
True when the chain, exactly as published, ends in a root Palisade trusts for BIMI. Null until checked.
The trusted root the chain ends in. Null when it is not trusted.
True when the certificate carries the BIMI mark-type attribute a VMC or CMC must have. Null until checked.
True when it is a mark certificate, one that embeds a logo; false when it is another kind of certificate; null when it could not be read.
True when the logo at location is byte for byte the one embedded in the certificate. Null when they were not compared.
True when the certificate names the audited domain. Null until checked.
Common name of the certificate's issuer.
Common name the certificate was issued to.
Start of the validity period, ISO 8601.
End of the validity period, ISO 8601.
The domains the certificate covers, from its subject alternative names.
Why the certificate failed, when it did.
The MTA-STS check. It does not count toward the overall score.
properties
Points this dimension takes off the overall score: 0 at full marks, negative otherwise. Only MX, SPF, DKIM, DMARC and BIMI are counted, and only SPF and DMARC when the domain is parked.
Verdict: "pass", "warn" or "fail"; "in progress" for a DMARC policy short of full reject or MTA-STS in testing mode; "info" when optional MTA-STS or TLS-RPT is not set up. DKIM reports "error" when the catalogue of sending services Palisade probes was unavailable, so no selector was probed and the result says nothing about the domain.
What was found that is not a problem, such as "spf-success". MTA-STS and TLS-RPT write sentences instead of codes.
Problems that break or undermine the mechanism, as stable codes such as "spf-no-record". A host can follow a colon, as in "spf-lookup-failed:spf.example.com". MTA-STS and TLS-RPT write sentences instead of codes.
Risks worth fixing that do not break the mechanism, such as "spf-low-ttl". MTA-STS and TLS-RPT write sentences instead of codes.
The MTA-STS setup as a state: "mta-sts-enforce", "mta-sts-testing", "mta-sts-none-mode", "mta-sts-missing", "mta-sts-dns-only" (a TXT record but no reachable policy), "mta-sts-mx-mismatch" (the policy misses an MX host) or "mta-sts-invalid".
properties
The verdict this state carries: "pass", "warn", "fail", "in progress" or "info".
Stable identifier for what was found, safe to branch on. The field holding this object lists its values.
Points this state earns toward its dimension. Unlike the dimension's own score, it counts up from 0.
Codes for lesser problems found alongside the state, such as "spf-ptr-unrecommended". Usually empty.
The record at _mta-sts.<domain>. Null when none, or more than one, is published.
The policy served at https://mta-sts.<domain>/.well-known/mta-sts.txt, verbatim. Null when it could not be fetched.
The policy mode: "enforce", "testing" or "none". Null when there is no policy to read.
The mx: patterns the policy covers.
The policy max_age in seconds. Null when there is no readable value.
The id= of the TXT record. Senders fetch the policy again when it changes.
The TLS-RPT check. It does not count toward the overall score.
properties
Points this dimension takes off the overall score: 0 at full marks, negative otherwise. Only MX, SPF, DKIM, DMARC and BIMI are counted, and only SPF and DMARC when the domain is parked.
Verdict: "pass", "warn" or "fail"; "in progress" for a DMARC policy short of full reject or MTA-STS in testing mode; "info" when optional MTA-STS or TLS-RPT is not set up. DKIM reports "error" when the catalogue of sending services Palisade probes was unavailable, so no selector was probed and the result says nothing about the domain.
What was found that is not a problem, such as "spf-success". MTA-STS and TLS-RPT write sentences instead of codes.
Problems that break or undermine the mechanism, as stable codes such as "spf-no-record". A host can follow a colon, as in "spf-lookup-failed:spf.example.com". MTA-STS and TLS-RPT write sentences instead of codes.
Risks worth fixing that do not break the mechanism, such as "spf-low-ttl". MTA-STS and TLS-RPT write sentences instead of codes.
The TLS-RPT record as a state: "tls-rpt-present", "tls-rpt-missing" or "tls-rpt-invalid".
properties
The verdict this state carries: "pass", "warn", "fail", "in progress" or "info".
Stable identifier for what was found, safe to branch on. The field holding this object lists its values.
Points this state earns toward its dimension. Unlike the dimension's own score, it counts up from 0.
Codes for lesser problems found alongside the state, such as "spf-ptr-unrecommended". Usually empty.
The record at _smtp._tls.<domain>. Null when none, or more than one, is published.
Where TLS failure reports go: the valid rua= destinations, each mailto: or https://.
Read a stored activation scan
/tools/activation-scanReturn the most recent audit stored for a domain by GET /tools/audit?store_scan=true, so a scan run on the marketing site survives the sign-up round trip without being run again. Reports the same public DNS findings the audit does, and expires 24 hours after the scan. Authentication is not required.
Query parameters
Example request
curl "https://api.palisade.email/tools/activation-scan"
Responses
Success
Response body
12530 · Max: 1000 · Max: 7items
mx, spf, dkim, dmarc, bimi, mtaSts, tlsRpt1 · Max length: 32fail, warn, info1 · Max length: 1000items
1 · Max length: 20001 · Max length: 1000253properties
8192items
SET_UP_MX_RECORD, SET_UP_SPF_RECORD, CLEANUP_SPF_RECORD, REDUCE_SPF_LOOKUPS1 · Max: 31 · Max length: 500properties
1 · Max length: 128253email-security-scoreIdentify the mailbox provider
/tools/mailbox-providerrequires authIdentify which mailbox provider hosts a domain's inbound mail, from its live MX records. Returns a null provider when the MX records match no known provider, when the domain has no MX at all, or when a security gateway sits in front and hides the provider behind it. Authentication is optional.
Query parameters
Example request
curl "https://api.palisade.email/tools/mailbox-provider" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
Null when the MX records match no known mailbox provider, or when the domain has no MX at all.
properties
Validate an SPF include
/tools/validate-includerequires authCheck that a domain is usable as an SPF include: and count the DNS lookups it costs, so you can tell before adding it whether it will push a record past the ten-lookup limit. The count includes the include itself. Callable with an API key or a dashboard session. The browser tool reaches this same endpoint with a captcha token instead, which is why you may see it called without credentials; a captcha is not something an API client can produce, so it is not part of this contract.
Query parameters
The domain to test as an SPF include: target, e.g. _spf.google.com.
Example request
curl "https://api.palisade.email/tools/validate-include" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
DNS lookups the include costs, counting the include itself. Only present when valid is true.
Why the domain is not usable as an SPF include. Only present when valid is false.
Look up DNS records
/tools/dns-lookuprequires authRead a host's TXT, MX, NS, A and CNAME records from live DNS in one call. Record types that resolve to nothing are simply absent from the array rather than reported as an error. Authentication is optional.
Request body
The host to resolve.
Example request
curl -X POST "https://api.palisade.email/tools/dns-lookup" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30" \
-H "Content-Type: application/json" \
-d '{
"host": "string"
}'
Responses
Success
Response body
items
TXT, MX, NS, A, CNAMEMX preference. Only present on MX records.
Analyze email headers
/tools/header-analyzerequires authParse a raw email header block and report what the receiving path concluded: the SPF, DKIM and DMARC verdicts each hop recorded, whether those domains align with the From domain, the DKIM signatures and ARC chain present, and the delivery hops with the delay at each. With include_dns_validation left on, the From domain's SPF, DMARC and DKIM records are also read from live DNS so a verdict can be checked against what is published now. Callable with an API key or a dashboard session. The browser tool reaches this same endpoint with a captcha token instead, which is why you may see it called without credentials; a captcha is not something an API client can produce, so it is not part of this contract. The request body is snake_case, but the analysis in the response keeps camelCase field names (authenticationResults, receivedHops, dnsValidation) rather than the API-wide convention.
Request body
10 · Max length: 100000trueExample request
curl -X POST "https://api.palisade.email/tools/header-analyze" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30" \
-H "Content-Type: application/json" \
-d '{
"headers": "string",
"include_dns_validation": true
}'
Responses
Success
Response body
properties
pass, fail, softfail, neutral, none, temperror, permerror or unknown.
pass, fail, softfail, neutral, none, temperror, permerror or unknown.
pass, fail, softfail, neutral, none, temperror, permerror or unknown.
Whether the SPF domain aligns with the From domain, strictly or relaxed.
items
pass, fail, softfail, neutral, none, temperror, permerror or unknown.
pass, fail, softfail, neutral, none, temperror, permerror or unknown.
pass, fail, softfail, neutral, none, temperror, permerror or unknown.
Microsoft's composite authentication verdict, when present.
items
items
items
Milliseconds spent at this hop, or null when it cannot be derived.
Live DNS read for the From domain. Null when include_dns_validation was false.
properties
items
Webhooks
List webhook endpoints
/webhook-endpointsrequires authQuery parameters
Headers
2025-04-30, unstableExample request
curl "https://api.palisade.email/webhook-endpoints" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
WebhookEndpoint
Event types this endpoint receives. An empty array means every event, including ones added later — not none.
items
domain.created, domain.updated, domain.deleted, domain.monitoring.activated, domain.monitoring.failed, domain.monitoring.drifted, domain.monitoring.recovered, domain.hosted_record.ready, domain.hosted_record.error, domain.score_changed, domain.policy_changed, mta_sts.enabled, mta_sts.updated, mta_sts.disabled, task.opened, task.completed, task.canceled, task.dismissed, task.reopened, organization.updated, member.added, member.updated, member.removed, invitation.created, invitation.revoked, group.created, group.updated, group.deletedENABLED receives events. DISABLED was turned off by you. AUTO_DISABLED was turned off by Palisade after repeated delivery failures and stays off until you re-enable it, which also clears the failure count.
ENABLED, DISABLED, AUTO_DISABLEDLast 4 characters of the signing secret. The full secret is returned only at creation.
API version the payload shape is pinned to, captured when the endpoint was created.
0properties
Create a webhook endpoint
/webhook-endpointsrequires authCreates an endpoint. The response is the only time the signing secret is returned in full; store it immediately.
Headers
2025-04-30, unstableRequest body
500Event types this endpoint receives. Omit it, or send an empty array, to receive every event including ones added later.
items
domain.created, domain.updated, domain.deleted, domain.monitoring.activated, domain.monitoring.failed, domain.monitoring.drifted, domain.monitoring.recovered, domain.hosted_record.ready, domain.hosted_record.error, domain.score_changed, domain.policy_changed, mta_sts.enabled, mta_sts.updated, mta_sts.disabled, task.opened, task.completed, task.canceled, task.dismissed, task.reopened, organization.updated, member.added, member.updated, member.removed, invitation.created, invitation.revoked, group.created, group.updated, group.deletedExample request
curl -X POST "https://api.palisade.email/webhook-endpoints" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"description": "string",
"enabled_events": [
"domain.created"
]
}'
Responses
Created
Response body
Event types this endpoint receives. An empty array means every event, including ones added later — not none.
items
domain.created, domain.updated, domain.deleted, domain.monitoring.activated, domain.monitoring.failed, domain.monitoring.drifted, domain.monitoring.recovered, domain.hosted_record.ready, domain.hosted_record.error, domain.score_changed, domain.policy_changed, mta_sts.enabled, mta_sts.updated, mta_sts.disabled, task.opened, task.completed, task.canceled, task.dismissed, task.reopened, organization.updated, member.added, member.updated, member.removed, invitation.created, invitation.revoked, group.created, group.updated, group.deletedENABLED receives events. DISABLED was turned off by you. AUTO_DISABLED was turned off by Palisade after repeated delivery failures and stays off until you re-enable it, which also clears the failure count.
ENABLED, DISABLED, AUTO_DISABLEDLast 4 characters of the signing secret. The full secret is returned only at creation.
API version the payload shape is pinned to, captured when the endpoint was created.
0The signing secret, shown once. Store it now; it cannot be retrieved later.
Get a webhook endpoint
/webhook-endpoints/{id}requires authPath parameters
Headers
2025-04-30, unstableExample request
curl "https://api.palisade.email/webhook-endpoints/<id>" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
Event types this endpoint receives. An empty array means every event, including ones added later — not none.
items
domain.created, domain.updated, domain.deleted, domain.monitoring.activated, domain.monitoring.failed, domain.monitoring.drifted, domain.monitoring.recovered, domain.hosted_record.ready, domain.hosted_record.error, domain.score_changed, domain.policy_changed, mta_sts.enabled, mta_sts.updated, mta_sts.disabled, task.opened, task.completed, task.canceled, task.dismissed, task.reopened, organization.updated, member.added, member.updated, member.removed, invitation.created, invitation.revoked, group.created, group.updated, group.deletedENABLED receives events. DISABLED was turned off by you. AUTO_DISABLED was turned off by Palisade after repeated delivery failures and stays off until you re-enable it, which also clears the failure count.
ENABLED, DISABLED, AUTO_DISABLEDLast 4 characters of the signing secret. The full secret is returned only at creation.
API version the payload shape is pinned to, captured when the endpoint was created.
0Update a webhook endpoint
/webhook-endpoints/{id}requires authPath parameters
Headers
2025-04-30, unstableRequest body
500items
domain.created, domain.updated, domain.deleted, domain.monitoring.activated, domain.monitoring.failed, domain.monitoring.drifted, domain.monitoring.recovered, domain.hosted_record.ready, domain.hosted_record.error, domain.score_changed, domain.policy_changed, mta_sts.enabled, mta_sts.updated, mta_sts.disabled, task.opened, task.completed, task.canceled, task.dismissed, task.reopened, organization.updated, member.added, member.updated, member.removed, invitation.created, invitation.revoked, group.created, group.updated, group.deletedENABLED, DISABLEDExample request
curl -X POST "https://api.palisade.email/webhook-endpoints/<id>" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"description": "string",
"enabled_events": [
"domain.created"
],
"status": "ENABLED"
}'
Responses
Success
Response body
Event types this endpoint receives. An empty array means every event, including ones added later — not none.
items
domain.created, domain.updated, domain.deleted, domain.monitoring.activated, domain.monitoring.failed, domain.monitoring.drifted, domain.monitoring.recovered, domain.hosted_record.ready, domain.hosted_record.error, domain.score_changed, domain.policy_changed, mta_sts.enabled, mta_sts.updated, mta_sts.disabled, task.opened, task.completed, task.canceled, task.dismissed, task.reopened, organization.updated, member.added, member.updated, member.removed, invitation.created, invitation.revoked, group.created, group.updated, group.deletedENABLED receives events. DISABLED was turned off by you. AUTO_DISABLED was turned off by Palisade after repeated delivery failures and stays off until you re-enable it, which also clears the failure count.
ENABLED, DISABLED, AUTO_DISABLEDLast 4 characters of the signing secret. The full secret is returned only at creation.
API version the payload shape is pinned to, captured when the endpoint was created.
0Delete a webhook endpoint
/webhook-endpoints/{id}requires authPath parameters
Headers
2025-04-30, unstableExample request
curl -X DELETE "https://api.palisade.email/webhook-endpoints/<id>" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Deleted
Response body
Rotate the signing secret
/webhook-endpoints/{id}/rotate-secretrequires authIssues a new signing secret and returns it once. The previous secret stops being valid immediately, so deliveries signed with it will fail verification.
Path parameters
Headers
2025-04-30, unstableExample request
curl -X POST "https://api.palisade.email/webhook-endpoints/<id>/rotate-secret" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
Event types this endpoint receives. An empty array means every event, including ones added later — not none.
items
domain.created, domain.updated, domain.deleted, domain.monitoring.activated, domain.monitoring.failed, domain.monitoring.drifted, domain.monitoring.recovered, domain.hosted_record.ready, domain.hosted_record.error, domain.score_changed, domain.policy_changed, mta_sts.enabled, mta_sts.updated, mta_sts.disabled, task.opened, task.completed, task.canceled, task.dismissed, task.reopened, organization.updated, member.added, member.updated, member.removed, invitation.created, invitation.revoked, group.created, group.updated, group.deletedENABLED receives events. DISABLED was turned off by you. AUTO_DISABLED was turned off by Palisade after repeated delivery failures and stays off until you re-enable it, which also clears the failure count.
ENABLED, DISABLED, AUTO_DISABLEDLast 4 characters of the signing secret. The full secret is returned only at creation.
API version the payload shape is pinned to, captured when the endpoint was created.
0The signing secret, shown once. Store it now; it cannot be retrieved later.
List webhook deliveries
/webhook-endpoints/{id}/deliveriesrequires authPath parameters
Query parameters
PENDING, SUCCEEDED, FAILEDHeaders
2025-04-30, unstableExample request
curl "https://api.palisade.email/webhook-endpoints/<id>/deliveries" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
WebhookDelivery
domain.created, domain.updated, domain.deleted, domain.monitoring.activated, domain.monitoring.failed, domain.monitoring.drifted, domain.monitoring.recovered, domain.hosted_record.ready, domain.hosted_record.error, domain.score_changed, domain.policy_changed, mta_sts.enabled, mta_sts.updated, mta_sts.disabled, task.opened, task.completed, task.canceled, task.dismissed, task.reopened, organization.updated, member.added, member.updated, member.removed, invitation.created, invitation.revoked, group.created, group.updated, group.deletedPENDING, SUCCEEDED, FAILED0properties
List webhook event types
/webhook-eventsrequires authThe catalogue of event types an endpoint can subscribe to.
Headers
2025-04-30, unstableExample request
curl "https://api.palisade.email/webhook-events" \
-u "$PALISADE_API_KEY:" \
-H "Palisade-Version: 2025-04-30"
Responses
Success
Response body
WebhookEventDescriptor
domain.created, domain.updated, domain.deleted, domain.monitoring.activated, domain.monitoring.failed, domain.monitoring.drifted, domain.monitoring.recovered, domain.hosted_record.ready, domain.hosted_record.error, domain.score_changed, domain.policy_changed, mta_sts.enabled, mta_sts.updated, mta_sts.disabled, task.opened, task.completed, task.canceled, task.dismissed, task.reopened, organization.updated, member.added, member.updated, member.removed, invitation.created, invitation.revoked, group.created, group.updated, group.deleted