Send handwritten-style postcards, letters, notecards and gift cards through thanks.io, manage mailing lists and recipients, price orders before placing them, and track delivery.
thanks.io ships in the w6w first-party pack. It declares 25 actions, 3 health checks, and the host runs its code in a sandbox that never sees the credential.
io.w6w.thanksiothanks.io mails real, handwritten-looking direct mail — postcards, letters, notecards, Magnacards and gift cards — from an API call. A workflow can send any of those mailers to a mailing list or to recipients passed inline, price an order before placing it (the estimate endpoint charges nothing and mails nothing), then follow the order: track its delivery summary, list its individual pieces with per-piece status and QR-scan counts, cancel it while it is still in review, or replay it to the same or new recipients.
The app also manages the audience those mailers go to: mailing lists, single and bulk recipient creation, recipient updates and deletes, plus read access to handwriting styles, gift card brands, and image and message templates.
Every send action spends real money and mails a physical piece. Use the Estimate Order action, the preview flag, or the account’s API Testing Mode (which cancels orders) while building.
Three routes to the same 25 actions. The Workflow tab is generated from thanks.io's own manifest and carries its real ids, so it is copy-pasteable; the Code and CLI examples are the same call for any action on any app, so every app-specific value in them is a blank you fill in.
estimate-order Price a mailer without placing it: free, nothing is charged, printed or mailed, and no order is created. Send the same inputs you would send to the matching Send action; the vendor validates them exactly as the send would, so a payload that would be rejected is rejected here too.
giftcard-brand-list List the gift card brands and the amounts (in cents) each supports. Use a `brand_code` and one of its `available_amounts` in Send Gift Card.
handwriting-style-list List the handwriting styles available for a message. Use a `handwriting_style_id` from here in the Send actions.
image-template-list List the image templates on the account, optionally for one mailer type or sub-account. Use a template of the matching mailer type when sending.
mailing-list-create Create an empty mailing list. A QR code URL, if given, becomes the default QR code for orders placed with this list.
mailing-list-get Get a mailing list with its recipient count, scan and send statistics.
mailing-list-recipients-list List the recipients of a mailing list, optionally only those updated since a given time.
message-template-list List the message templates on the account, optionally for one mailer type or sub-account. Use a template of the matching mailer type when sending.
order-cancel Cancel an order that is still in Reviewing status; its credits are refunded to the account. An order that has moved past Reviewing cannot be cancelled.
order-items-list List the individual mail pieces of an order, one per recipient, with delivery status, delivery date, QR scan count, failure reason and recipient address.
order-replay SPENDS REAL MONEY and mails a physical piece to a real address when it is not a preview. Submit a copy of a previously placed order as a brand-new order: the same creative is charged and mailed again. The original is left untouched.
order-track Get an order with its delivery summary: counts of pieces delivered, printed, in transit, returned or failed, and QR scans.
recipient-create Add a recipient to a mailing list. With no valid mailing address but a valid email, thanks.io looks the street address up for an additional fee.
recipient-update Update the details of a recipient. Only the fields you give are sent.
recipients-create-multiple Add many recipients at once from a JSON array. A recipient with an email but no valid mailing address triggers a paid address lookup.
send-giftcard SPENDS REAL MONEY and mails a physical piece to a real address when it is not a preview. Send a folded 4.25x5.5 notecard with a gift card inside. The gift card value is charged on top of postage.
send-magnacard SPENDS REAL MONEY and mails a physical piece to a real address when it is not a preview. Send a Magnacard. Needs an image template or a front image URL.
send-notecard SPENDS REAL MONEY and mails a physical piece to a real address when it is not a preview. Send a folded 4.25x5.5 notecard in an envelope. Needs an image template or a front image URL.
send-postcard SPENDS REAL MONEY and mails a physical piece to a real address when it is not a preview. Send a 4x6, 6x9 or 6x11 postcard to a mailing list, inline recipients or a radius search.
send-windowed-letter SPENDS REAL MONEY and mails a physical piece to a real address when it is not a preview. Send a letter in a windowed envelope (the recipient address shows through the window).
send-windowless-letter SPENDS REAL MONEY and mails a physical piece to a real address when it is not a preview. Send a letter in a windowless envelope (the address is printed on the envelope).
A workflow step names the app and the action, and the editor fills in the
connection when you pick one. This is the Step shape from the
workflow spec, carrying thanks.io's real ids.
{
"manifestVersion": "2",
"name": "thanksio-example",
"steps": [
{
"id": "estimate-order",
"uses": {
"app": "io.w6w.thanksio",
"action": "estimate-order",
"connection": "conn_YOUR_CONNECTION_ID"
},
"with": {
"mailerType": "<mailerType>"
}
}
]
}estimate-order giftcard-brand-list handwriting-style-list image-template-list mailing-list-create +20 more actions available
Every app-specific value here is a blank you have to fill in. An
app action is reached through the connection that authenticates it, so the
address is a connection id, not the app id — and connections belong to your account,
so a public page cannot know yours. Create one for thanks.io, then fill in
the three blanks: conn_YOUR_CONNECTION_ID, the action key, and the
parameters that action declares. The call itself is real — the shape is transcribed
from the studio's own snippet builder, which prints the same kind of blanks — but
nothing in it is specific to thanks.io. The Workflow tab is where this app's
real ids are.
npm install @w6w/sdkyarn add @w6w/sdkpnpm add @w6w/sdkdeno add npm:@w6w/sdkimport { W6wClient, isActionRun } from "@w6w/sdk";
// Reads W6W_BASE_URL and W6W_TOKEN from the environment when omitted.
const client = new W6wClient();
const envelope = await client.run({
urn: "conn_YOUR_CONNECTION_ID",
action: "estimate-order",
payload: {
mailerType: "<value>",
// mailingListIds: "<value>",
// recipients: "<value>",
// radiusSearch: "<value>",
// message: "<value>",
// messageTemplateId: "<value>",
// imageTemplateId: "<value>",
// frontImageUrl: "<value>",
// handwritingStyleId: "<value>",
// handwritingColor: "<value>",
// handwritingRealism: "<value>",
// qrcodeUrl: "<value>",
// size: "<value>",
// giftcardBrand: "<value>",
// giftcardAmountInCents: "<value>",
// subAccount: "<value>",
// notificationEmails: "<value>",
// sendStandardMail: "<value>",
// returnName: "<value>",
// returnAddress: "<value>",
// returnAddress2: "<value>",
// returnCity: "<value>",
// returnState: "<value>",
// returnPostalCode: "<value>",
// metadata: "<value>",
// extra: "<value>",
},
});
if (isActionRun(envelope)) console.log(envelope.value); npm install -g @w6w/cli w6w run conn_YOUR_CONNECTION_ID --action estimate-order --payload '{"mailerType":"<value>"}' Give an AI agent thanks.io — without giving it thanks.io's credentials. One MCP endpoint exposes every app, function and workflow the caller is entitled to, as tools it can discover and run. Access is granted per team while we onboard.
One tool call{
"name": "w6w_invoke",
"arguments": {
"ref": "app:io.w6w.thanksio#estimate-order",
"input": {
"mailerType": "<mailerType>"
}
}
}
Every tool names its target with a single ref. The
app: form above doesn't name a connection at all — the
host resolves which of the caller's thanks.io connections to sign
with, and refuses rather than guesses when the answer is ambiguous.
The token is attached host-side, at the moment of the call. It is never a tool argument, never in the model's context, and never in a transcript — so a prompt injection has nothing to exfiltrate.
Tools are derived per end user from what that person has actually connected and is entitled to — not one shared bot identity carrying the union of everyone's access.
Multi-step work runs on the workflow engine and returns a run handle the agent can poll — retries, branching and state survive the conversation that started them.
thanks.io's declared health checks are on the surface too, so an agent can tell "the vendor is down" from "your credential expired" before it burns a retry on either.
The MCP surface is part of the hosted platform. thanks.io itself is MIT, and the runtime that executes it is source-available (FSL).
thanks.io declares its own checks, so its health is a property of the app rather than something the host guesses at.
Unsigned GET https://api.thanks.io/api/v2/mailing-lists/?items_per_page=1. A 401 carrying thanks.io's own `{"message":"Unauthenticated."}` body passes: it proves the API and its auth layer are answering. Credential validity is the derived `auth:*` check's job.