---
title: codespar_notify
description: Send notifications via WhatsApp, email or SMS. Z-API for WhatsApp in Brazil, Twilio for SMS and international WhatsApp, SendGrid for email.
---

import { Callout } from "fumadocs-ui/components/callout";

<MetaToolHeader tool="codespar_notify" />

The unified messaging interface for transactional notifications: order confirmations, shipping updates, payment receipts, KYC nudges. The agent picks the channel, the recipient and the text (or a template); CodeSpar picks the provider.

## Actions

<MetaToolActions tool="codespar_notify" />

## Example

A WhatsApp message with free text.

<Split min={380}>
<SplitPane label="Call · tools/call">

```json title="arguments"
{
  "name": "codespar_notify",
  "arguments": {
    "channel": "whatsapp",
    "to": "+5500000000000",
    "message": "Your order order_0000 has shipped."
  }
}
```

</SplitPane>
<SplitPane label="Result">

Result shape: see runtime. The tool document names no result field. The published document is [`/v1/meta-tools.json`](https://api.codespar.dev/v1/meta-tools.json).

</SplitPane>
</Split>

## When to use

- **A transactional message after an event**: a settlement, a label, an invoice. The [Webhook Listener cookbook](/docs/cookbooks/webhook-listener) fires it from the settlement event.
- **Templates** when the provider requires an approved template instead of free text: pass `template` and `variables`.
- **Delivery confirmation** lands later as a webhook; wire a [trigger](/docs/concepts/triggers) on `notify.delivered` if you need it.

## Arguments

| Field | Type | Required | Description |
|---|---|---|---|
| `channel` | `string` | Yes | `whatsapp`, `email` or `sms` |
| `to` | `string` | Yes | Recipient phone number (E.164, `+5511…`) for WhatsApp and SMS, email address for email |
| `message` | `string` | No | Custom message text |
| `template` | `string` | No | Message template name, when the provider requires an approved template |
| `variables` | `object` | No | Template variables, when `template` is set |

## Errors and what to do

| Error | Cause | What to do |
|---|---|---|
| `invalid_args` | `channel` or `to` missing, or a `channel` outside `whatsapp` / `email` / `sms`. Nothing is sent. | Fix the call against the Arguments table. |
| `no_eligible_providers` | No provider for that channel is connected on this project. Nothing is sent. | Connect Z-API, Twilio or SendGrid (see Notes) via [`codespar_manage_connections`](/docs/concepts/meta-tools/manage-connections). |

## Money and mandate

Nothing moves, and no mandate is involved. What the call does is send a message to a real recipient in the operator's name, so the guardrail that applies is the bulk-outbound cap described under [guardrails](/docs/concepts/guardrails): bulk outbound messaging above the tenant's threshold requires human approval.

## Related

- [`codespar_ship`](/docs/concepts/meta-tools/ship): the tracking code a shipping update carries
- [`codespar_charge`](/docs/concepts/meta-tools/charge) and [`codespar_pay`](/docs/concepts/meta-tools/pay): the settlements a receipt message follows
- [Triggers](/docs/concepts/triggers): subscribe to `notify.delivered`
- [Pix Payment Agent cookbook](/docs/cookbooks/pix-payment-agent): `codespar_notify` paired with `codespar_pay`

## Notes

**Rails, as previously documented.** WhatsApp in Brazil routes to Z-API (`path_secret` auth, phone-id scoped), preferred for lower latency and template-free chat on verified business numbers; WhatsApp elsewhere and SMS route to Twilio (account SID plus auth token; Twilio's WhatsApp body is form-encoded, unlike Z-API's JSON); email routes to SendGrid (API key with `mail.send` scope).

**Operator setup.** Z-API: `path_secret` auth_type, a phone-id embedded in the path plus a companion `Client-Token` header, one connection per Z-API instance ([path_secret auth](/docs/concepts/authentication#path-secret-auth)). Twilio: account SID and auth token, the same credentials for SMS, voice and Twilio WhatsApp. SendGrid: API key.

**Result shape (SDK), as previously documented.** `{ id, status: "queued" | "sent" | "delivered" | "failed", channel, delivered_at? }`. This revision did not re-verify that list against the runtime.

**From the SDK.** There is no typed wrapper; `session.execute("codespar_notify", arguments)` takes the same arguments as the MCP call (an earlier version of this page wrote `recipient` and `subject`, which the schema does not declare; the recipient field is `to`).
