First-party app
thanks.io

thanks.io

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.

stable MarketingCommunication

About

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.

App id
io.w6w.thanksio
Version
0.1.0
Author
w6w
Licence
MIT
Categories
Marketing · Communication

Overview

thanks.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.

Build with thanks.io

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

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.

List Gift Card Brands

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.

List Handwriting Styles

handwriting-style-list

List the handwriting styles available for a message. Use a `handwriting_style_id` from here in the Send actions.

List Image Templates

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.

Create Mailing List

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.

Get Mailing List

mailing-list-get

Get a mailing list with its recipient count, scan and send statistics.

List Mailing Lists

mailing-list-list

List the mailing lists on the account.

List Mailing List Recipients

mailing-list-recipients-list

List the recipients of a mailing list, optionally only those updated since a given time.

List Message Templates

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.

Cancel Order

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.

List Order Items

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.

List Orders

order-list

List recent orders, optionally filtered by sub-account or mailer type.

Replay Order

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.

Track Order

order-track

Get an order with its delivery summary: counts of pieces delivered, printed, in transit, returned or failed, and QR scans.

Create Recipient

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.

Delete Recipient

recipient-delete

Delete a recipient from its mailing list.

Get Recipient

recipient-get

Get a recipient by ID.

Update Recipient

recipient-update

Update the details of a recipient. Only the fields you give are sent.

Create Multiple Recipients

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 Gift Card

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

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

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

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

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

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>"
      }
    }
  ]
}

Here are some of the things you can do

  • Estimate Order

    read
    estimate-order
  • List Gift Card Brands

    read
    giftcard-brand-list
  • List Handwriting Styles

    read
    handwriting-style-list
  • List Image Templates

    read
    image-template-list
  • Create Mailing List

    perform
    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.

Install
npm install @w6w/sdk
yarn add @w6w/sdk
pnpm add @w6w/sdk
deno add npm:@w6w/sdk
Code
import { 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);
Install the CLI
npm install -g @w6w/cli
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.

What the agent gets

Credentials it can't read

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.

A tool surface scoped to the caller

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.

A durable workflow in one call

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.

Health-aware discovery

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).

Request MCP access

Health checks

thanks.io declares its own checks, so its health is a property of the app rather than something the host guesses at.

service

thanks.io platform status

dependency

API reachable

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.

quota

API rate limit and balance