diff --git a/.changeset/sms-e164-recipient.md b/.changeset/sms-e164-recipient.md new file mode 100644 index 0000000..f1147d4 --- /dev/null +++ b/.changeset/sms-e164-recipient.md @@ -0,0 +1,9 @@ +--- +"@senderkit/sdk": patch +"@senderkit/cli": patch +--- + +Document that SMS recipients must be an E.164 phone number, matching the hosted API's validation. The API now rejects a non-E.164 SMS `to` with `400 invalid_recipient` (for both template and raw sends) instead of accepting it and failing later at dispatch. + +- The `senderkit_send_raw` `to` field description now spells out the per-channel recipient formats — including the E.164 requirement for `sms` — bringing it in line with `senderkit_send`, which already documented it. This flows through to the `senderkit send-raw` CLI help. +- The SDK README's SMS example now notes the E.164 requirement and the `400 invalid_recipient` response. diff --git a/packages/sdk/README.md b/packages/sdk/README.md index d5fcbae..8d92003 100644 --- a/packages/sdk/README.md +++ b/packages/sdk/README.md @@ -100,7 +100,7 @@ await senderkit.sendRaw({ }); ``` -SMS, push, and web-push work the same way — switch the `channel` and the `content` shape: +SMS, push, and web-push work the same way — switch the `channel` and the `content` shape. SMS recipients must be an [E.164](https://en.wikipedia.org/wiki/E.164) phone number (e.g. `+15555550123`); anything else is rejected with `400 invalid_recipient`. ```ts await senderkit.sendRaw({ diff --git a/packages/sdk/src/mcp-schemas.ts b/packages/sdk/src/mcp-schemas.ts index adc9b47..6d58a8e 100644 --- a/packages/sdk/src/mcp-schemas.ts +++ b/packages/sdk/src/mcp-schemas.ts @@ -193,7 +193,9 @@ export const sendRawInput = { to: z .string() .describe( - "Recipient address. For web-push, the JSON-encoded browser PushSubscription (endpoint + keys).", + "Recipient address for the chosen channel: an email address (email), an " + + "E.164 phone number such as +15551234567 (sms), a device token (push), or " + + "the JSON-encoded browser PushSubscription — endpoint + keys — (web-push).", ), // email subject: z.string().optional().describe("Email subject (email)."), diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 967acc2..b92f44c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,10 +7,10 @@ settings: overrides: postcss: '>=8.5.18 <9' esbuild: '>=0.28.1' - hono: '>=4.12.27 <5' + hono: '>=4.12.34 <5' '@hono/node-server': '>=2.0.5 <3' js-yaml: '>=4.3.0 <5' - fast-uri: '>=3.1.4 <4' + fast-uri: '>=3.1.5 <4' sharp: '>=0.35.0 <0.36' body-parser: '>=2.3.0 <3' read-yaml-file: ^2.1.0 @@ -421,7 +421,7 @@ packages: resolution: {integrity: sha512-eWpQYr67tqJLeaSUl0Q+TquuYfUdTibpOJlUMV2FfUP7+KqCC5TufnwnlXL6mobZBJbGAYRd7ZvEBDCbLInjhg==} engines: {node: '>=20'} peerDependencies: - hono: '>=4.12.27 <5' + hono: '>=4.12.34 <5' '@img/colour@1.1.0': resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==} @@ -1291,8 +1291,8 @@ packages: resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} engines: {node: '>=8.6.0'} - fast-uri@3.1.4: - resolution: {integrity: sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==} + fast-uri@3.1.5: + resolution: {integrity: sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==} fastq@1.20.1: resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} @@ -1380,8 +1380,8 @@ packages: resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} engines: {node: '>= 0.4'} - hono@4.12.32: - resolution: {integrity: sha512-XcuyW9qE2kJn07PkecMOBd5Vq/hMy7mmGw+idz1yblbg9N17ijJODrvPkn7/dwL3Kulj8LcRJ69DLOWf91dRUg==} + hono@4.13.0: + resolution: {integrity: sha512-jhunvfHWxd7J5EFfSgH4xsYJzSe/lfqbUCxiyyeaQasUsXeEHXtzVid+7EOGByc5JnFa23SSFL3Y2RV/z1T+eQ==} engines: {node: '>=16.9.0'} html-escaper@2.0.2: @@ -2447,9 +2447,9 @@ snapshots: '@esbuild/win32-x64@0.28.1': optional: true - '@hono/node-server@2.0.12(hono@4.12.32)': + '@hono/node-server@2.0.12(hono@4.13.0)': dependencies: - hono: 4.12.32 + hono: 4.13.0 '@img/colour@1.1.0': optional: true @@ -2597,7 +2597,7 @@ snapshots: '@modelcontextprotocol/sdk@1.30.0(supports-color@7.2.0)(zod@4.4.3)': dependencies: - '@hono/node-server': 2.0.12(hono@4.12.32) + '@hono/node-server': 2.0.12(hono@4.13.0) ajv: 8.20.0 ajv-formats: 3.0.1(ajv@8.20.0) content-type: 1.0.5 @@ -2607,7 +2607,7 @@ snapshots: eventsource-parser: 3.1.0 express: 5.2.1(supports-color@7.2.0) express-rate-limit: 8.6.1(express@5.2.1(supports-color@7.2.0))(supports-color@7.2.0) - hono: 4.12.32 + hono: 4.13.0 jose: 6.2.5 json-schema-typed: 8.0.2 pkce-challenge: 5.0.1 @@ -2906,7 +2906,7 @@ snapshots: ajv@8.20.0: dependencies: fast-deep-equal: 3.1.3 - fast-uri: 3.1.4 + fast-uri: 3.1.5 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 @@ -3179,7 +3179,7 @@ snapshots: merge2: 1.4.1 micromatch: 4.0.8 - fast-uri@3.1.4: {} + fast-uri@3.1.5: {} fastq@1.20.1: dependencies: @@ -3279,7 +3279,7 @@ snapshots: dependencies: function-bind: 1.1.2 - hono@4.12.32: {} + hono@4.13.0: {} html-escaper@2.0.2: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 5e447f1..19cbb50 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -10,10 +10,10 @@ allowBuilds: overrides: postcss: ">=8.5.18 <9" esbuild: ">=0.28.1" - hono: ">=4.12.27 <5" + hono: ">=4.12.34 <5" "@hono/node-server": ">=2.0.5 <3" js-yaml: ">=4.3.0 <5" - fast-uri: ">=3.1.4 <4" + fast-uri: ">=3.1.5 <4" sharp: ">=0.35.0 <0.36" body-parser: ">=2.3.0 <3" read-yaml-file: "^2.1.0"