Postalytics
MARKETING · MARKETING
Direct-mail campaigns, templates, contacts, and delivery events in that account.
Acts as the person, not as itself
Each user connects their own account. Every call carries both identities — the agent and the person it is acting for — so the agent can never reach past what that individual can already do.
Credentials never touch the agent
Tokens live in the vault and attach server-side at call time. The agent holds a session, not a secret, and revoking access does not mean rotating a key.
Every call on the record
Who asked, which agent acted, which action ran, and the verdict that let it through — one audit trail across every integration, not one per vendor.
What an agent can do
Each action is granted on its own. An agent allowed to read is not thereby allowed to write, and the scope beside each row is what the acting user must have connected for it to run at all.
postalytics_delete_account_by_idWRITEDESTRUCTIVE, AND WIDER THAN ITS NAME. Deleting a Postalytics account also permanently deletes every campaign, template and list belonging to it -- the vendor states this on the operation itself. It deletes SUB-accounts and sub-user accounts only: a parent account cannot be removed through the API and needs Postalytics support. Nothing here is recoverable and there is no recycle bin to read the deletion back out of.
postalytics_delete_campaign_by_idWRITEDESTRUCTIVE. Permanently delete a campaign by its drop id, with its counters and its endpoint. Pieces already mailed are already in the post and are not recalled by this.
postalytics_delete_contacts_by_idWRITEDESTRUCTIVE. Remove one contact, by its CONTACT id, from the list it is on. Pieces already mailed to that contact are unaffected.
postalytics_delete_lists_suppression_by_idWRITEDESTRUCTIVE, AND IT REMOVES A SAFETY RAIL. Deleting a suppression list deletes every do-not-mail address on it, so addresses a campaign was skipping become mailable again. Read the list's contacts out first if they matter.
postalytics_delete_lists_suppression_contact_by_list_id_by_contact_idWRITEDESTRUCTIVE, AND IT MAKES AN ADDRESS MAILABLE AGAIN. Removing a contact from a suppression list removes the instruction not to mail them, so the next campaign that would have skipped that address will print and post to it.
postalytics_delete_templates_by_idWRITEDESTRUCTIVE. Permanently delete a template by id. Campaigns already built from it keep their preview images; new campaigns can no longer reference it.
postalytics_delete_webhooks_by_idWRITEDESTRUCTIVE. Delete a webhook so Postalytics stops posting that campaign's events to it. The campaign and its events are untouched.
postalytics_get_account_by_idREADRead one Postalytics account by its numeric account id -- the same record shape as the connected-account read. Reaches the connection's own account and the sub-accounts beneath it; an id outside that subtree is not yours to read. Agentic Fabriq REDACTS the api_key field out of the response before returning it.
postalytics_get_account_meREADRead the Postalytics account this connection's API key belongs to -- its account id, username, email, company, phone, name, address and creation date. This is the cheapest way to confirm which account a key reaches, which matters on Postalytics because an agency holds a separate key per master account and per client sub-account and nothing else on the wire says which one you are holding. Agentic Fabriq REDACTS the api_key field out of the response before returning it.
postalytics_get_campaign_by_idREADRead one campaign by its DROP id -- the `drop_id` from the campaign list or from the create response, not the `campaign_id` that appears beside it. The record carries the same counters the list returns.
postalytics_get_campaign_details_by_idREADRead a campaign's SETTINGS rather than its statistics: its drop id, name, endpoint id, status and contact list id. Statuses are 1 Sent, 0 Pending, -1 Draft Mode, 9 or 10 Processing. This is where the campaign's `ContactListId` comes from, which the contact tools then address.
postalytics_get_campaign_event_by_id_by_dataidREADThe same event stream narrowed to ONE recipient within the campaign: `id` is the campaign's drop id and `dataid` is the mail piece's data id. Paged the same way, and it answers 400 `Campaign events not found` when the campaign has produced no events yet.
postalytics_get_campaign_events_by_idREADList the most recent delivery and engagement events for a campaign, newest first and paged. Event names Postalytics returns are Mail Piece Created, Addressed, Mailed, In Transit, In Local Area, Processed for Delivery, Returned To Sender, Re-Routed, pURL Opened and purl Completed; online activity carries the visited URL in its metadata and offline activity carries none. ⚠ A CAMPAIGN WITH NO EVENTS YET ANSWERS 400 `Campaign events not found` rather than an empty array (measured 2026-09-19) -- an empty collection, not a failure. A test-mode campaign produces no events at all.
postalytics_get_campaignsREADList every campaign in the account with its delivery and engagement counters -- audience, delivered, in transit, in local area, returned, unique visitors, conversions, pageviews -- plus its drop id, its endpoint id and whether it is in live or test mode. ⚠ ON AN ACCOUNT WITH NO CAMPAIGNS THIS ANSWERS 400 `Campaign not found`, not an empty array (measured 2026-09-19: 400 before any campaign existed, 200 with the full record immediately after one was created). That 400 is an EMPTY COLLECTION, not a bad request and not a bad key.
postalytics_get_campaigns_dripsREADList every triggered drip campaign in the account as a name and an `endpoint_id` pair. This is the cheapest way to find the endpoint the Send tool addresses; the campaign read gives the rest of the detail. Answers `{"drips": []}` on an account with none -- a proper empty collection, unlike the campaign list.
postalytics_get_contactsREADList the contact lists in the account -- each with its `contact_list_id`, its name, how many contacts it holds and when it was created. A campaign's own list appears here under the campaign's name, so this is one way to find the id the contact tools address (the campaign-settings tool is the other, and is exact). ⚠ THE LIST IS NOT IMMEDIATELY CONSISTENT: measured 2026-09-19, a list created moments earlier by a campaign was still absent from this answer while the same list read in full through the list-contacts tool; it appeared on a later call. An empty or short answer is worth re-reading before it is believed.
postalytics_get_contacts_by_idREADList the contacts on one contact list, addressed by the CONTACT LIST id (from the campaign settings tool), paged by an offset and a limit. `start` is a row number beginning at 1 and `limit` excludes the starting row; a limit above 100 or equal to 0 is silently clamped to 100. Each contact carries its `contact_id`, its address fields and its var_field_1 .. var_field_50 merge values.
postalytics_get_contacts_details_by_idREADRead one contact by its CONTACT id (not a list id -- the sibling tool takes a list id at almost the same path, which is the easiest mix-up to make here). ⚠ THE RESPONSE SPEAKS A THIRD VOCABULARY: this record comes back PascalCase (`FirstName`, `Address`, `VarField1`, `ContactListId`) while the list read of the same contact returns snake_case (`first_name`, `address_street`, `var_field_1`). It also carries the contact's pURL and QR code, which the list read does not.
postalytics_get_flowREADList the account's Postalytics flows. NOT IN THE VENDOR'S OWN SDK -- the 43 client methods of postalytics-python 1.0.471 do not include it -- and it is live: the sealed research ledger records it as `get_all_flows`, the route oracle answers 401 for it credential-free while `/api/v1/flowzz` answers 404, and it answered 200 `[]` to a real key (all measured 2026-09-19). It ships on that evidence.
postalytics_get_lists_suppressionREADList the account's suppression lists with each one's id, name, country and contact total. A suppression list is the do-not-mail list: an address on it is skipped by a campaign rather than printed, which is the one place on this API where adding a record PREVENTS postage being spent. The optional `id` narrows the answer to one list.
postalytics_get_lists_suppression_by_idREADRead one suppression list by id -- its name, type, country, creation date and how many contacts it holds. The contacts themselves come from the list-contacts tool.
postalytics_get_lists_suppression_contact_by_list_id_by_contact_idREADRead one contact on one suppression list, by the list id and the contact's `dataId`.
postalytics_get_lists_suppression_contacts_by_list_idREADList the contacts on one suppression list, with the list's own summary alongside them. Each contact carries a `dataId`, its standardised address -- Postalytics normalises and ZIP+4s what you send -- and a `hasValidAddress` flag. Paged by `offset`.
postalytics_get_templatesREADList the account's mail-piece templates with their html, size, page count, proofed and double-sided flags and signed preview-image URLs. ⚠ ON AN ACCOUNT WITH NO TEMPLATES THIS ANSWERS 400 `Template not found`, not an empty array (measured 2026-09-19: 400 before any template existed, 200 with the full record immediately after one was created). That 400 is an EMPTY COLLECTION, not a bad request and not a bad key -- which is exactly why this endpoint is NOT this integration's connection probe, though the vendor's own reference uses it as its authentication example.
postalytics_get_templates_by_idREADRead one template by id, with its html and its signed front and back preview-image URLs.
postalytics_get_userREADRead the user record behind this connection -- name, username, email, company and billing addresses, user type, domain and joined date. ⚠ THIS RECORD ECHOES THE API KEY as its `UserGUID` field; Agentic Fabriq REDACTS that field before returning the response.
postalytics_get_user_by_user_idREADRead one user by id. Must be a sub-account or a sub-user of the requester. ⚠ Echoes that user's API key as `UserGUID`; Agentic Fabriq REDACTS it.
postalytics_get_webhooksREADList the account's webhooks, each with the campaign it watches, its endpoint id, its target url and whether it is subscribed. Answers `[]` on an account with none -- a proper empty collection.
postalytics_get_webhooks_by_idREADRead one webhook by id.
postalytics_post_accountWRITECreate a Postalytics sub-account beneath the requester's account. The response carries the NEW account's own API key and user id, which is how an agency platform provisions a client: store that key and make the client's subsequent calls with it. `username` must be unique and unused, and `password` must be at least 8 characters with an uppercase letter, a lowercase letter, a number and a special character -- Postalytics answers 400 naming the field otherwise. Creating an account costs nothing and mails nothing.
postalytics_post_campaignsWRITECreate a direct-mail campaign (a 'drop'). A TEMPLATE MUST EXIST AND BE PROOFED FIRST and its id passed as `TemplateFrontId`. The response carries the new `drop_id`; the campaign's ENDPOINT id -- the thing the Send tool addresses -- is then read from the campaign list, the campaign read or the drip list. ⚠ `IsLiveMode` DECIDES WHETHER THIS CAMPAIGN SPENDS POSTAGE. Created false, the campaign is a test drip and sends against it print and mail nothing; created or switched true, every subsequent send is a real physical mail piece billed to the account. Creating the campaign itself mails nothing either way.
postalytics_post_contactsWRITEAdd a contact to a contact list. `contact_list_id` IS REQUIRED and must name an existing list -- without it, and with a list id of 0, Postalytics answers 400 `Validation error` and names nothing (measured 2026-09-19). Get the id from the campaign settings tool. Creating a contact mails nothing; whether a piece is ever sent to it is decided by the Send tool and the campaign's live mode.
postalytics_post_lists_suppressionWRITECreate a suppression (do-not-mail) list. `Name` is what you will recognise it by and `Country` is a two-letter code -- Postalytics expands `US` to `United States` in the response. Costs nothing and mails nothing.
postalytics_post_lists_suppression_contacts_by_list_idWRITEAdd an address to a suppression list so campaigns stop mailing it. Postalytics standardises what you send -- measured 2026-09-19, `200 Berkeley St, Boston, MA 02116` came back as `200 BERKELEY ST / BOSTON / 02116-5022` with `hasValidAddress: true` -- and the response is the whole list with its new total. This is the operation that PREVENTS postage rather than spending it.
postalytics_post_loginlinkWRITEMint a short-lived auto-login URL for the account this connection holds, so an embedding platform can pop a Postalytics Express Window with the account already signed in. THE LINK IS A BEARER OF THAT SESSION and the vendor says it is valid only for a short period and should be used immediately -- treat the returned URL as a credential. `url` is required and is prepended to the link for white-labelled accounts; without it Postalytics uses its own postalytics.com host. `id` optionally deep-links to a template or a campaign. ⚠ Postalytics also requires an `api_key` field in this body, naming the account the link signs into; Agentic Fabriq fills it from this connection's own stored credential and does NOT accept it as an argument, so no API key is ever passed to or logged by a tool call. A link for a different sub-account is minted by connecting that sub-account's key.
postalytics_post_send_by_end_pointWRITE⚠ THIS SENDS PHYSICAL MAIL AND SPENDS REAL POSTAGE WHEN THE CAMPAIGN IS LIVE. Kick off a triggered drip to one recipient. `end_point` is the campaign's endpoint id -- from the drip list, the campaign list or the campaign settings -- and it, not this call, decides the template, the postage, the return address and the pURL redirect. WHETHER ANYTHING IS ACTUALLY PRINTED AND MAILED IS THE CAMPAIGN'S `is_live_mode`, NOT A PARAMETER HERE: against a test-mode campaign the call is accepted and nothing is mailed (measured 2026-09-19 -- 200 with a send_date, audience unchanged at 0 and no event produced); against a live campaign the same call prints and posts a piece and bills the account. Required fields are first_name, last_name and the recipient's street, city, two-letter state and valid ZIP; var_field_1 .. var_field_35 carry merge values into the template.
postalytics_post_templatesWRITECreate a mail-piece template, TWO WAYS. Either pass `front` and `back` as image URLs for full-size backgrounds carrying no other text, or pass the whole piece as `html` with `is_full_html` true, built to Postalytics' template standards. ⚠ `is_proofed` true OVERRIDES POSTALYTICS' PROOFING PROCESS and the vendor states it takes no responsibility for templates created that way -- but a campaign cannot be created from an unproofed template, so this is the flag that lets an API-built template be used. Creating a template costs nothing and mails nothing.
postalytics_post_webhooksWRITECreate a webhook so Postalytics posts a campaign's events out to your own endpoint. `url` must be a reachable endpoint and `is_subscribed` must be 1 for it to fire. ⚠ `campaign_id` IS THE CAMPAIGN'S DROP ID, not the `campaign_id` field that appears beside it in the campaign list: measured 2026-09-19, drop 93227 was accepted (200) and campaign_id 82244 for the same campaign answered 400 `Validation error`. WHICH events are delivered is set in the Postalytics application, not here; the vendor says that will be exposed on this endpoint in a future release.
postalytics_put_accountWRITEUpdate an existing Postalytics account -- a free-standing account or a sub-account of an agency, addressed by `account_id` IN THE BODY rather than in the path. The response carries that account's API key and user id. Send only the fields you mean to change.
postalytics_put_campaign_by_idWRITE⚠ THIS TOGGLES POSTAGE SPENDING. It flips a triggered-drip or automated-file campaign from Test mode to Live and back -- there is no request body and no target state to pass, so the call is its own inverse and a second call returns the campaign to where it was. In LIVE mode every subsequent Send against this campaign's endpoint prints and mails a real physical piece and bills the account; in TEST mode a send is accepted and mails nothing. The id is the campaign's DROP id. Read the campaign back and check `is_live_mode` rather than assuming the direction of the flip.
postalytics_put_contactsWRITEUpdate a contact's details in place. The contact is addressed by `contact_id` and `contact_list_id` IN THE BODY, not in the path. Same snake_case vocabulary as the create. ⚠ MEASURED 2026-09-19 THE PROVIDER FAILS THIS OPERATION ITSELF: every call naming a REAL contact answered 400 `Error updating contact -An unexpected error occurred. Reference: <id>` and changed nothing -- 17 attempts across two credential carriers, three lists, contacts created by the create tool and by a send, and eight body shapes including the vendor SDK's own example and the record exactly as the list tool returned it. A NONEXISTENT contact id answers 400 `Validation error` instead, so the server finds the contact and its update handler throws after that. A 400 quoting a Reference id here is Postalytics' defect, not your arguments; there is no shape of this request that succeeds today. To change a contact, delete it and create it again.
postalytics_put_lists_suppression_contact_by_list_id_by_contact_idWRITEUpdate one record on a suppression list in place, addressed by the list id and the contact's `dataId`: its name, company, email, phone, occupation, website and merge fields. ⚠ THE ADDRESS CANNOT BE CHANGED HERE, and this tool does not offer it. Measured 2026-09-19, sending any of Address, Address2, City, State or Zip answers 400 `Updating suppression list contact address fields is not allowed`, naming all five -- so they are absent from this tool while the ADD still takes them. To change which address is suppressed, delete the record and add the new one.
postalytics_put_webhooksWRITEUpdate a webhook in place -- its url or its subscribed flag. The webhook is addressed by `campaign_id` (the drop id) IN THE BODY, not in the path.
Often connected alongside
Put Postalytics behind one governed endpoint.
Same permissions, same audit trail, whatever else you connect next.