### First send setup prompt (first-send.txt) Source: https://www.postshiba.com/docs/connect-mcp Use this prompt in Cursor after connecting the server to get set up for the first send: set up sending domain, get SMTP credentials, and configure the app. ```text I've signed up to PostShiba and have set up my first cluster. Could you help me get set up for our first send? Set up our sending domain, get SMTP credentials, and work out how to get our app configured to use it. Also help me with adding the DNS records or telling me what to do whilst you work on the code ``` -------------------------------- ### Install the SDK with Maven Source: https://www.postshiba.com/docs/send-with-java Run this command in the cloned postshiba-java repository to install the SDK locally. ```sh ./mvnw install ``` -------------------------------- ### Install postshiba-go from GitHub Source: https://www.postshiba.com/docs/send-with-go Install the PostShiba Go module from GitHub. The module is not on a package registry yet. ```sh go get github.com/postshiba/postshiba-go ``` -------------------------------- ### Install @postshiba/trigger and @trigger.dev/sdk Source: https://www.postshiba.com/docs/send-with-trigger Install the required packages using npm on Node 18 or later. ```sh npm install github:postshiba/postshiba-trigger @trigger.dev/sdk ``` -------------------------------- ### Install @postshiba/inngest and inngest Source: https://www.postshiba.com/docs/send-with-inngest Install the required packages for the Inngest adapter. Requires Node 18 or later. ```sh npm install github:postshiba/postshiba-inngest inngest ``` -------------------------------- ### Tenant response example Source: https://www.postshiba.com/docs/guides/build-an-esp Example JSON response from the tenant creation call. Shows the tenant id, name, slug, and suspended flag. ```json { "id": "WbLcFd", "name": "Acme Florist", "slug": "acme-florist", "suspended": false } ``` -------------------------------- ### Install PostShiba Python SDK via pip from GitHub Source: https://www.postshiba.com/docs/send-with-python Installs the PostShiba Python client from the GitHub repository using pip. Run this command in your terminal before using the SDK. ```sh pip install git+https://github.com/postshiba/postshiba-python.git ``` -------------------------------- ### Install PostShiba Django backend Source: https://www.postshiba.com/docs/send-with-django Install the PostShiba Python package with the Django extra using pip. ```sh pip install "git+https://github.com/postshiba/postshiba-python.git#egg=postshiba[django]" ``` -------------------------------- ### Webhook event response example Source: https://www.postshiba.com/docs/api-reference/sending Example of how the unique arguments are flattened onto a SendGrid delivery event. ```json { "event": "delivered", "email": "you@example.com", "campaign_id": "cmp_123", "category": "transactional", "account": "team_1", "site": "docs", "unique_args": { "campaign_id": "cmp_123", "category": "transactional", "account": "team_1", "site": "docs" } } ``` -------------------------------- ### Install PostShiba dependency in mix.exs Source: https://www.postshiba.com/docs/send-with-elixir Add the PostShiba dependency to your mix.exs file to install the SDK. ```elixir {:postshiba, git: "https://github.com/postshiba/postshiba-elixir.git"} ``` -------------------------------- ### Install PostShiba Node package Source: https://www.postshiba.com/docs/send-with-nestjs Install the PostShiba Node package via npm. Requires an API key, a verified domain, and a cluster with sending_ready true. ```sh npm install github:postshiba/postshiba-node ``` -------------------------------- ### Global CSS and HTML Template Example Source: https://www.postshiba.com/docs/dashboard/templates/css This example shows a global CSS stylesheet and a corresponding HTML template using Liquid variables. The CSS defines styles for the body, container, and button, while the HTML uses these classes and Liquid placeholders. ```css body { margin: 0; background: #f4f4f5; color: #18181b; font-family: ui-sans-serif, system-ui, sans-serif; } .container { max-width: 560px; margin: 0 auto; padding: 32px 16px; } .button { display: inline-block; padding: 10px 16px; background: #18181b; color: #fafafa; text-decoration: none; border-radius: 6px; } ``` ```html

Hi {{ name }},

Continue

``` -------------------------------- ### GET /api/v1/teams/:obfuscated_team_id/firewall - response.json Source: https://www.postshiba.com/docs/api-reference/firewall Example JSON response for the GET firewall request. Shows the structure with enabled_checks, available_checks, and entries. ```json { "enabled_checks": [ "temp_providers", "plus_addressing" ], "available_checks": [ "temp_providers", "free_providers", "plus_addressing" ], "entries": [ { "id": "BnMkLo", "list": "deny", "value": "mailinator.com", "created_at": "2026-08-31T00:00:00Z" } ] } ``` -------------------------------- ### GET /api/v1/teams/:obfuscated_team_id/recipients Request Source: https://www.postshiba.com/docs/api-reference/recipients Example cURL request to retrieve recipient details for a specific team. ```bash curl -sS -X GET \ -H 'Authorization: Bearer YOUR_API_KEY' \ https://app.postshiba.com/api/v1/teams/KjkAJW/recipients ``` -------------------------------- ### Call provisionCustomer from onboarding job Source: https://www.postshiba.com/docs/guides/build-an-esp Imports PostShibaClient and calls provisionCustomer with example values. Logs the resulting tenant ID, domain ID, DKIM details, return path, optional DMARC, and SMTP username. Requires environment variable CAPSULE_API_KEY. ```javascript import { PostShibaClient } from "./postshiba-client.js"; const capsule = new PostShibaClient({ baseUrl: "https://app.postshiba.com", apiKey: process.env.CAPSULE_API_KEY, teamId: "KjkAJW", clusterId: "NmQpXr", }); const setup = await capsule.provisionCustomer({ name: "Acme Florist", slug: "acme-florist", domain: "mail.acme.example", }); console.log({ capsuleTenantId: setup.tenant.id, capsuleTenantSlug: setup.tenant.slug, capsuleDomainId: setup.sendingDomain.id, dkimHost: setup.sendingDomain.dkim_cname_host, dkimType: setup.sendingDomain.dkim_manual ? "TXT" : "CNAME", dkimValue: setup.sendingDomain.dkim_manual ? setup.sendingDomain.dkim_txt : setup.sendingDomain.dkim_cname_target, returnPathHost: setup.sendingDomain.return_path_host, returnPathValue: setup.sendingDomain.return_path_target, optionalDmarc: setup.sendingDomain.dmarc_record, smtpUsername: setup.smtpCredential.username, }); ``` -------------------------------- ### Create the tenant with create-tenant.sh Source: https://www.postshiba.com/docs/guides/build-ai-agent-inbox Use this command to create a new tenant for the agent. Replace the placeholders with your specific team and API credentials. ```bash curl -sS \ --request POST \ --url "$CAPSULE_URL/api/v1/teams/$TEAM_ID/tenants" \ --header "Authorization: Bearer $CAPSULE_API_KEY" \ --header "Content-Type: application/json" \ --data '{ "tenant": { "name": "Acme agents", "slug": "acme-agents" } }' ``` -------------------------------- ### GET /api/v1/teams/:obfuscated_team_id/analytics response Source: https://www.postshiba.com/docs/api-reference/analytics Example JSON response containing delivery totals and dimension-based rows. ```json { "dimension": "mx_provider", "window": { "since": "2026-09-15T12:00:00Z", "until": "2026-09-16T12:00:00Z" }, "totals": { "processed": 10, "delivered": 8, "deferred": 1, "bounce": 1, "spamreport": 0, "unsubscribe": 0 }, "rows": [ { "key": "gmail", "label": "gmail", "processed": 10, "delivered": 8, "deferred": 1, "bounce": 1, "spamreport": 0, "unsubscribe": 0 } ] } ``` -------------------------------- ### GET /api/v1/sending_domains/:id/can_i_send_this - JSON response Source: https://www.postshiba.com/docs/api-reference/domains Example response from the GET endpoint. Contains status, report details including subject, from, score, checks, SPF, DKIM, DMARC, SpamAssassin score, and report URL. ```json { "status": "ready", "report": { "subject": "Can I Send This check for mail.example.com", "from": "hello@mail.example.com", "score": { "pass": 8, "total": 10 }, "checks": [ { "id": "spf", "kind": "pass", "detail": "SPF aligned" } ], "spf": { "kind": "pass", "detail": "aligned" }, "dkim": { "kind": "pass", "detail": "valid" }, "dmarc": { "kind": "none", "detail": "" }, "spamassassin": { "score": 1.2 }, "report_url": "https://canisendthis.com/tok_cist" } } ``` -------------------------------- ### Create a PostShiba client Source: https://www.postshiba.com/docs/send-with-elixir Initialize a new client using PostShiba.new/3. Pass nil as the base_url to use the default production URL. ```elixir client = PostShiba.new("YOUR_API_KEY", nil, "KjkAJW") ``` -------------------------------- ### GET /api/v1/teams/:obfuscated_team_id/analytics request Source: https://www.postshiba.com/docs/api-reference/analytics Example cURL request to fetch analytics for a specific team using an API key. ```bash curl -sS -X GET \ -H 'Authorization: Bearer YOUR_API_KEY' \ https://app.postshiba.com/api/v1/teams/KjkAJW/analytics ``` -------------------------------- ### GET /api/v1/inboxes/:id - JSON response Source: https://www.postshiba.com/docs/api-reference/inboxes Example response containing inbox details including webhook secret and MX status. ```json { "id": "PqRzMn", "name": "agent", "address": "inbabc123@inbound.capsule.test", "local_part": "inbabc123", "host": "inbound.capsule.test", "tenant_id": "WbLcFd", "webhook_url": "https://hooks.example.com/mail", "webhook_format": "json", "webhook_secret": "hex-secret", "mx_status": "not_required", "inbound_emails_per_hour": 25, "retention_hours": 168 } ``` -------------------------------- ### Cluster creation response JSON Source: https://www.postshiba.com/docs/guides/send-transactional-email Example response from the cluster creation request, showing the cluster details and 'sending_ready': true. ```json { "id": "NmQpXr", "name": "production", "region": "manual", "size": "small", "plan": "nano", "ip_assignment": "shared", "desired_status": "active", "status": "active", "sending_ready": true } ``` -------------------------------- ### GET /api/v1/teams/:obfuscated_team_id/recipients Response Source: https://www.postshiba.com/docs/api-reference/recipients Example JSON response containing recipient status, suppression list, and recent send events. ```json { "email": "dest@example.com", "can_receive": false, "suppressions": [ { "id": "YtReWq", "email": "blocked@example.com", "reason": "manual", "tenant_id": "WbLcFd", "tenant": "default", "created_at": "2026-08-30T00:00:00Z" } ], "firewall": null, "sends": [ { "id": "JkLmNp", "event_type": "dropped", "message_id": null, "occurred_at": "2026-08-29T00:00:00Z", "explanation": "We did not send this message because the address is on your suppression list." } ] } ``` -------------------------------- ### List clusters response Source: https://www.postshiba.com/docs/api-reference/clusters Example JSON response from the GET clusters endpoint. Shows a single cluster with fields like classification, endpoints, throttles, and assigned IP. ```json [ { "id": "NmQpXr", "name": "edge", "region": "manual", "size": "small", "plan": "nano", "emails_per_hour": 100, "emails_per_day": 600, "base_emails_per_hour": 100, "base_emails_per_day": 600, "boost": null, "ip_assignment": "shared", "desired_status": "active", "status": "active", "smtp_endpoint": "smtp.capsule.test:587", "http_endpoint": "smtp.capsule.test:8000", "classification": "transactional", "assigned_ip": { "address": "203.0.113.2", "status": "active" }, "sending_ips": [ { "address": "203.0.113.2", "status": "active", "kind": "shared", "classification": "transactional", "weight": 100, "provider": null } ], "sending_ready": true } ] ``` -------------------------------- ### PostShibaClient class with provisionCustomer method Source: https://www.postshiba.com/docs/guides/build-an-esp Defines a client for the PostShiba API. The provisionCustomer method makes three sequential API calls: create a tenant, create a sending domain, and create an SMTP credential. It returns an object containing the tenant, sending domain, and SMTP credential. The request method handles authentication and error responses. ```javascript export class PostShibaClient { constructor({ baseUrl, apiKey, teamId, clusterId }) { this.baseUrl = baseUrl; this.apiKey = apiKey; this.teamId = teamId; this.clusterId = clusterId; } async request(path, { method = "GET", body } = {}) { const response = await fetch(`${this.baseUrl}${path}`, { method, headers: { Authorization: `Bearer ${this.apiKey}`, ...(body ? { "Content-Type": "application/json" } : {}), }, body: body ? JSON.stringify(body) : undefined, }); if (!response.ok) { throw new Error(`PostShiba ${method} ${path}: ${response.status} ${await response.text()}`); } if (response.status === 204) return null; return response.json(); } async provisionCustomer({ name, slug, domain }) { const tenant = await this.request( `/api/v1/teams/${this.teamId}/tenants`, { method: "POST", body: { tenant: { name, slug } }, }, ); const sendingDomain = await this.request( `/api/v1/teams/${this.teamId}/sending_domains`, { method: "POST", body: { sending_domain: { name: domain, tenant_id: tenant.id, }, }, }, ); const smtpCredential = await this.request( `/api/v1/teams/${this.teamId}/clusters/${this.clusterId}/smtp_credentials`, { method: "POST", body: { smtp_credential: { tenant_id: tenant.id, }, }, }, ); return { tenant, sendingDomain, smtpCredential }; } } ``` -------------------------------- ### Create a shared-IP cluster (create-cluster.txt) Source: https://www.postshiba.com/docs/connect-mcp Use this prompt to create a shared-IP cluster. It instructs to poll get_cluster until sending_ready is true and to stop if create_cluster returns 403. ```text Create a shared-IP cluster for this team. Name it after the team. Poll get_cluster until sending_ready is true before you send. If create_cluster returns 403, stop. See Does PostShiba require production approval? ``` -------------------------------- ### Initialize PostShiba client Source: https://www.postshiba.com/docs/send-with-dart Create a client instance by passing your API key and teamId. ```dart import 'package:postshiba/postshiba.dart'; final client = PostShiba("YOUR_API_KEY", teamId: "KjkAJW"); ``` -------------------------------- ### Install PostShiba Convex component Source: https://www.postshiba.com/docs/send-with-convex Install the package using npm on Node 18 or later. ```sh npm install github:postshiba/postshiba-convex ``` -------------------------------- ### Initialize PostShiba Client Source: https://www.postshiba.com/docs/send-with-ruby Create a new PostShiba client instance using your API key and team ID. ```ruby postshiba = PostShiba.new(api_key: "YOUR_API_KEY", team_id: "KjkAJW") ``` -------------------------------- ### GET /api/v1/tenants/:id Source: https://www.postshiba.com/docs/api-reference/tenants Get a single tenant by its public id. Includes the default tenant. ```APIDOC ## GET /api/v1/tenants/:id ### Description Get one tenant. Includes the default tenant. ### Method GET ### Endpoint /api/v1/tenants/:id ### Parameters #### Path Parameters - **id** (string) - Required - Public tenant id. ### Request Example ```bash curl -sS -X GET \ -H 'Authorization: Bearer YOUR_API_KEY' \ https://app.postshiba.com/api/v1/tenants/:tenant_id ``` ### Response #### Success Response (200) - **id** (string) - Public tenant id. - **name** (string) - Tenant name. - **slug** (string) - Tenant slug. - **suspended** (boolean) - Whether sending is suspended. #### Response Example ```json { "id": "WbLcFd", "name": "Acme Florist", "slug": "acme-florist", "suspended": false } ``` ``` -------------------------------- ### GET /api/v1/message_events/:id Source: https://www.postshiba.com/docs/api-reference/events Get one event and its payload. A Support key omits payload. ```APIDOC ## GET /api/v1/message_events/:id ### Description Get one event and its payload. A Support key omits payload. ### Method GET ### Endpoint /api/v1/message_events/:id ### Parameters #### Path Parameters - **id** (string) - Required - Public event id. ### Request Example ```bash curl -sS -X GET \ -H 'Authorization: Bearer YOUR_API_KEY' \ https://app.postshiba.com/api/v1/message_events/:message_event_id ``` ### Response #### Success Response (200) - **id** (string) - Event ID. - **event_type** (string) - Type of event (e.g., delivered). - **recipient** (string) - Recipient email address. - **sender** (string) - Sender email address. - **message_id** (string) - Message ID. - **mx_provider** (string) - MX provider. - **sending_ip** (string) - Sending IP address. - **bounce_classification** (string|null) - Bounce classification, null for delivered. - **bounce_reason** (string|null) - Bounce reason, null for delivered. - **smtp_code** (string|null) - SMTP code, null for delivered. - **enhanced_code** (string|null) - Enhanced code, null for delivered. - **explanation** (string|null) - Explanation, null for delivered. - **occurred_at** (string) - Timestamp of event occurrence. - **drain_status** (string) - Drain status. - **tenant_id** (string) - Public tenant ID. - **sending_domain_id** (string) - Public sending domain ID. - **node_id** (string) - Node ID. - **payload** (object) - Payload data. #### Response Example ```json { "id": "JkLmNp", "event_type": "delivered", "recipient": "dest@example.com", "sender": "hello@mail.example.com", "message_id": "abc", "mx_provider": "gmail", "sending_ip": "203.0.113.10", "bounce_classification": null, "bounce_reason": null, "smtp_code": null, "enhanced_code": null, "explanation": null, "occurred_at": "2026-08-29T00:00:00Z", "drain_status": "pending", "tenant_id": "WbLcFd", "sending_domain_id": "HsVtYk", "node_id": "ZxHvTb", "payload": { "event": "delivered" } } ``` ``` -------------------------------- ### Create Inngest client Source: https://www.postshiba.com/docs/send-with-inngest Create an Inngest app client. Pass its `step` into `sendEmail`. ```ts import { Inngest } from "inngest" export const inngest = new Inngest({ id: "app" }) ``` -------------------------------- ### Send a sandbox test email (send-test-email.txt) Source: https://www.postshiba.com/docs/connect-mcp Use send_on_cluster with sandbox true for a sandbox send, not send_email. A live send requires sending_ready, a verified From domain, and a live credential. MCP cannot set Idempotency-Key; never use the whoami email as From. ```text Send a sandbox message with send_on_cluster and sandbox true. Do not use send_email for a sandbox send. A live send needs sending_ready, a verified From domain, and a live credential. MCP cannot set Idempotency-Key. Never use the whoami email as From. Omit from or use a verified sending domain. ``` -------------------------------- ### Create SMTP credentials in create-credential.sh and response Source: https://www.postshiba.com/docs/guides/build-ai-agent-inbox Creates SMTP credentials for the cluster and returns the credential details. ```bash curl -sS \ --request POST \ --url "$CAPSULE_URL/api/v1/teams/$TEAM_ID/clusters/NmQpXr/smtp_credentials" \ --header "Authorization: Bearer $CAPSULE_API_KEY" \ --header "Content-Type: application/json" \ --data '{ "smtp_credential": { "tenant_id": "WbLcFd" } }' ``` ```json { "id": "RvWsXq", "username": "smtp_9", "password": "once-only-password", "tenant_id": "WbLcFd", "tenant": "acme-agents", "cluster_id": "NmQpXr" } ``` -------------------------------- ### GET /api/v1/templates/:id Source: https://www.postshiba.com/docs/api-reference/templates Get one template by public id or alias. Returns the current draft fields. ```APIDOC ## GET /api/v1/templates/:id ### Description Get one template by public id or alias. Returns the current draft fields. ### Method GET ### Endpoint /api/v1/templates/:id ### Parameters #### Path Parameters - **id** (string) - Required - Public template id or alias. ### Request Example ```bash curl -sS -X GET \ -H 'Authorization: Bearer YOUR_API_KEY' \ https://app.postshiba.com/api/v1/templates/:email_template_id ``` ### Response #### Success Response (200) - **id** (string) - Template public id. - **name** (string) - Template name. - **alias** (string) - Template alias. - **from** (string) - From email address. - **reply_to** (string) - Reply-to email address. - **subject** (string) - Email subject. - **html** (string) - HTML content. - **text** (string) - Plain text content. - **css** (string) - Global CSS. - **sample_data** (object) - Sample data for template variables. - **published** (boolean) - Whether the template is published. - **published_at** (string) - Timestamp of last publish. - **has_unpublished_changes** (boolean) - Whether there are unpublished changes. - **created_at** (string) - Creation timestamp. - **updated_at** (string) - Last update timestamp. #### Response Example ```json { "id": "TpLmQr", "name": "Welcome", "alias": "welcome", "from": "hello@mail.example.com", "reply_to": null, "subject": "Hi {{ name }}", "html": "

Hi {{ name }}

", "text": "Hi {{ name }}", "css": "p { color: #18181b; }", "sample_data": { "name": "Ada" }, "published": true, "published_at": "2026-09-11T12:00:00.000Z", "has_unpublished_changes": false, "created_at": "2026-09-11T12:00:00.000Z", "updated_at": "2026-09-11T12:00:00.000Z" } ``` ``` -------------------------------- ### GET /api/v1/inboxes/:inbox_id/inbound_messages/:id Source: https://www.postshiba.com/docs/api-reference/messages Get one alive message, including raw MIME and attachment content_base64. ```APIDOC ## GET /api/v1/inboxes/:inbox_id/inbound_messages/:id ### Description Get one alive message, including raw MIME and attachment content_base64. ### Method GET ### Endpoint /api/v1/inboxes/:inbox_id/inbound_messages/:id ### Parameters #### Path Parameters - **inbox_id** (string) - Required - Public inbox id - **id** (string) - Required - Public inbound message id ### Request Example ```bash curl -sS -X GET \ -H 'Authorization: Bearer YOUR_API_KEY' \ https://app.postshiba.com/api/v1/inboxes/:inbox_id/inbound_messages/:inbound_message_id ``` ### Response #### Success Response (200) - **id** (string) - Public inbound message id - **inbox_id** (string) - Public inbox id - **to** (string) - Recipient email address - **from** (string) - Sender email address - **subject** (string) - Email subject - **text** (string) - Plain text body - **html** (string) - HTML body - **thread_id** (string) - Thread identifier - **headers** (object) - Email headers - **envelope** (object) - Envelope details - **authentication** (object) - Authentication results - **attachments** (array) - List of attachments including content_base64 - **expires_at** (string) - Purge time - **drain_status** (string) - pending, stored, retrying, delivered, or dead - **raw** (string) - Raw MIME content #### Response Example ```json { "id": "GxTyVu", "inbox_id": "PqRzMn", "to": "inbabc123@inbound.capsule.test", "from": "sender@example.com", "subject": "Hello", "text": "Hi", "html": "

Hi

", "thread_id": "thread", "headers": {}, "envelope": { "mail_from": "sender@example.com", "rcpt_to": "inbabc123@inbound.capsule.test", "plus_tag": "thread" }, "authentication": { "spf": { "result": "pass", "domain": "example.com" }, "dkim": [ { "result": "pass", "domain": "example.com", "selector": "google" } ], "dmarc": { "result": "pass", "policy": "none", "aligned": true }, "arc": { "result": "none" } }, "attachments": [ { "filename": "photo.png", "content_type": "image/png", "size": 70, "content_base64": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==" } ], "expires_at": "2026-08-30T00:00:00Z", "drain_status": "stored", "raw": "From: sender@example.com\n" } ``` ``` -------------------------------- ### Create PostShiba client with NewClient and WithTeamID Source: https://www.postshiba.com/docs/send-with-go Create a PostShiba client by passing your API key to NewClient. Add WithTeamID for team-scoped paths. ```go client := postshiba.NewClient("YOUR_API_KEY", postshiba.WithTeamID("KjkAJW")) ``` -------------------------------- ### Create an inbox with verified sending domain (create-mailbox.txt) Source: https://www.postshiba.com/docs/connect-mcp Use create_inbox to create an inbox. Omit host and sending_domain_id for a hosted address; for a domain-bound address, set local_part and host to a verified sending domain or subdomain. Copy signing secrets from the dashboard, not MCP. ```text Create an inbox with create_inbox. Omit host and sending_domain_id for a hosted address. For a domain-bound address, set local_part and host to a verified sending domain or a subdomain of it. sending_domain_id is inferred from host. Copy signing secrets from the dashboard inbox page, not from MCP. ``` -------------------------------- ### Get one tenant GET /api/v1/tenants/:id Source: https://www.postshiba.com/docs/api-reference/tenants Retrieves details for a specific tenant by its public ID. This endpoint includes the default tenant. ```bash curl -sS -X GET \ -H 'Authorization: Bearer YOUR_API_KEY' \ https://app.postshiba.com/api/v1/tenants/:tenant_id ``` ```json { "id": "WbLcFd", "name": "Acme Florist", "slug": "acme-florist", "suspended": false } ```