Message

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

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.
post/send-message/direct-send

Request

  • Base URL
    https://api.spurnow.com
  • Auth
    HTTP bearer

Request body

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

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

Example request

{
  "to": "919876543210",
  "text": "Hi Priya, your order #4512 shipped today and should reach you by Friday. Reply here if anything looks wrong.",
  "options": {
    "from": "919876543210"
  }
}

Response

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

idnumber required

Internal Spur message ID.

metaMessageIdstring

Provider message id (Meta/Infobip) when available.

sentDateTimestring date-time

Time when message was sent from Spur.

contentobject

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.

warningstring

Additional delivery warning for specific template categories.

noticestring

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.

heldboolean

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.

Example response

{
  "id": 981273,
  "metaMessageId": "wamid.HBgMOTE5ODc2NTQzMjEwFQIAERgSNkQ5MjhEMUE5QkQ0NTM0RkI1AA==",
  "sentDateTime": "2026-02-14T10:20:30.000Z",
  "deliveryPath": "plain",
  "warning": "Marketing messages are not guaranteed delivery due to WhatsApp per-user marketing limits.",
  "notice": "Meta accepted this Direct Send message. It is billed at Meta's utility rate, and delivery can take a few minutes. Don't send it again just because it hasn't arrived yet; Spur's message-delivery webhook reports when it is sent, delivered, read or failed."
}

Changes

No recorded changes to this operation across all 1 revision of this API.