---
title: "Send a utility text outside the 24-hour window with Meta Direct Send"
method: POST
path: "/send-message/direct-send"
tags: ["Message"]
---

# Send a utility text outside the 24-hour window with Meta Direct Send

`POST /send-message/direct-send`

## Request

- Base URL: `https://api.spurnow.com`
- URL: `https://api.spurnow.com/send-message/direct-send`
- Auth: HTTP bearer

Send one plain-text WhatsApp message to one contact. Outside WhatsApp's 24-hour window it goes out through **Meta Direct Send**: a normal text message that Meta delivers as a **utility** message. You don't create or get a template approved: Meta creates (or reuses) one for each message, named `auto_generated_…`, visible in WhatsApp Manager and not editable or deletable. Inside the window it is an ordinary message.

## ⚠️ Read before you send

- **Utility content only:** replies, updates about an order, booking or account, and support. **No marketing or promotions**, no discount codes, no offers.
- **Misuse gets your whole WhatsApp Business Account, every number on it, restricted or banned by Meta.** Meta warns first, then caps utility messages, then blocks Direct Send for 7 days, then for 30 days, then removes access. **Spur cannot reverse or help with Meta's enforcement.**
- **Delivery can take a few minutes, and Meta may hold a message.** Direct Send messages are subject to Meta's business portfolio pacing: a message can be held for quality review (the response then carries `held: true`) and delivered later or dropped. A drop is reported only by the status webhook, with code 135000, which Spur's message-delivery webhook forwards. Don't send the same message again just because it hasn't arrived yet.
- **Every message is billed at Meta's utility rate.**

## How it works

- Direct Send is never converted to a Magic Message or a template. When it can't be used, the request fails with a clear error carrying `directSend.unavailable`, and nothing is sent. Use `POST /send-message` with an approved template instead.
- Meta has to enable Direct Send for your WhatsApp Business Account (Meta generally requires a messaging limit of 100,000 or unlimited). Spur learns Meta's answer from the first send; there is no way to ask Meta in advance. Spur does not gate this endpoint per workspace: only Spur's platform-wide kill switch can pause it.
- Only contacts who have messaged this number before. A number with no prior conversation is refused, and so are contacts who opted out.
- Only WhatsApp Cloud API and Onextel numbers. Text only, up to 1,024 characters. One contact per request; never loop this endpoint for campaigns (use broadcasts). Spur does not cap how often a contact is messaged: that judgement is yours, and Meta's enforcement lands on your account.

## Response

`deliveryPath` says how the message went out: `direct_send` or, inside the window, `plain`. A Direct Send response also carries `notice`, and `held: true` when Meta is holding the message for quality review.

## When it fails

Every refusal has one shape: `error: "Direct Send unavailable"`, a `message` you can show as is, and `directSend.unavailable` to switch on. Alongside it, `directSend` carries the number's Direct Send standing: `status` (UNKNOWN, ENABLED, NOT_ENABLED or BLOCKED), `wabaId`, `phoneNumberId`, `nextCheckAt`, `blockedUntil`, `rateLimitedUntil` and `requestAccessUrl` (Meta's Direct Send access request form, prefilled with the WABA id), plus `errorCode` (Meta's error code) when Meta answered with one.

- 403 `not_turned_on`: Spur has paused Direct Send for everyone.
- 400 `unsupported_number`: the number is not on WhatsApp Cloud API or Onextel, or has no WhatsApp Business Account id yet.
- 400 `too_long`: the text is over 1,024 characters.
- 400 `rejected`: Meta refused this message. `errorCode` is Meta's code and `message` explains it: for example 131026 (the customer can't receive WhatsApp messages), 131056 (too many messages to this customer in a short time), 132015 and 132016 (Meta paused or disabled the template it matched to this text).
- 409 `not_enabled`: Meta hasn't enabled Direct Send for this WhatsApp Business Account. Ask Meta through `requestAccessUrl`; Spur asks Meta again after `nextCheckAt`.
- 409 `blocked`: Meta has paused Direct Send for this account (code 139200, utility misuse) until `blockedUntil`.
- 409 `no_prior_inbound`: the contact has never messaged this number.
- 409 `opted_out`: the contact opted out.
- 429 `rate_limited`: Meta is limiting utility messages from this number (code 131064) until `rateLimitedUntil`.
- 503 `checking`: Spur is asking Meta whether Direct Send is enabled for this account; try again in a minute.
- 503 `unavailable`: Spur couldn't read the number's Direct Send state; try again shortly.
- 504 with `directSend.ambiguous: true` and no `unavailable`: Meta hasn't confirmed the message yet. It may still arrive, so don't resend straight away.
- 500 with `directSend.accepted: true` and no `unavailable`: WhatsApp accepted the message but Spur couldn't save it. Don't send it again.
- After a send, a message Meta held and then dropped fails on the status webhook with code 135000.

## Request body

- DirectSendMessageDto
  - `to` string, required: WhatsApp recipient: a phone number with country code and no spaces (e.g. "919876543210") or a BSUID (e.g. "IN.abc123"). WhatsApp groups are not supported.
  - `text` string, required: The message, as plain text, up to 1,024 characters. Utility content only: a reply, or an update about an order, booking, account or support request. No marketing or promotions.
  - `options` SendMessageOptionsDto
    - `from` string: ⚠️ IMPORTANT: Phone number to send from (with country code, no spaces). This field is CRITICAL when you have multiple WhatsApp channels connected. If not specified, the system will use the default channel which may not be the intended one. Always specify this to ensure messages are routed through the correct WhatsApp Business Account.

## Response `201`

Sent. `deliveryPath` is `direct_send` outside the window, `plain` inside it.

- DirectSendMessageResponseDto
  - `id` number, required: Internal Spur message ID.
  - `metaMessageId` string: Provider message id (Meta/Infobip) when available.
  - `sentDateTime` string, date-time: Time when message was sent from Spur.
  - `content` object: Channel/content payload saved with the message.
  - `deliveryPath` 'plain' | 'direct_send' | 'magic_message' | 'template': How the message actually went out: `plain` (a normal message), `direct_send` (a Meta Direct Send utility message), `magic_message` (outside the 24-hour window, the text was sent as a Magic Message template) or `template`.
  - `warning` string: Additional delivery warning for specific template categories.
  - `deliveryBoost` object, required
    - `enabled` boolean
    - `maxRetries` number
    - `retryWindowHours` number
    - `message` string
  - `notice` string: Present when the message went out through Direct Send: delivery can take a few minutes, Meta may hold it for quality review (see `held`), so do not send it again just because it has not arrived yet.
  - `held` boolean: True when Meta answered `held_for_quality_assessment`: business portfolio pacing is holding the message. It may be delivered later or dropped (status webhook code 135000). Don't send it again.

## Other responses

- `400`: The text is empty or longer than 1,024 characters, the recipient is a group, the number is not on Cloud API or Onextel, or Meta refused the message (`directSend.errorCode` is Meta’s code).
- `403`: Spur has paused Direct Send for everyone (the platform-wide kill switch).
- `409`: Meta has not enabled Direct Send for this WhatsApp Business Account, Meta has paused it, the contact has never messaged this number, or the contact opted out. `directSend` carries the number’s standing: the WABA id, the dates and Meta’s access form.
- `429`: Meta is limiting utility messages from this number (code 131064).
- `503`: Spur is checking with Meta whether Direct Send is enabled for this account, or could not check it. Try again in a minute.
- `504`: Meta didn't confirm the message in time. It may still arrive, so don't send it again straight away.

---

[API](https://skmtc.dev/spurnow/apis/spur-apis.md) - [All operations](https://skmtc.dev/spurnow/apis/spur-apis/llms.txt) - [OpenAPI document](https://skmtc.dev/spurnow/apis/spur-apis/revisions/27ca7bf002cb?raw)
