Menu/bookings/{booking_id}/messages

Send a message to the guest of a booking

POST/api/v1/bookings/{booking_id}/messages
Requires messages.write

Sends the text right away, the way the ZenHost inbox does, and answers once it is sent. platform writes on the messaging of the Sales Channel of the booking; email and sms use the guest contact details ZenHost holds. The message is attributed to your App: the host sees "Sent by" and the name of your App in the inbox.

To attach photos, send the same fields as multipart/form-data with up to 5 photos parts (JPEG, PNG, WebP or AVIF, 10 MB each), on platform only; email and SMS answer validation_failed. In practice a whole call stays under about 4.5 MB (see below). The text and each photo reach the guest as separate messages, the way the ZenHost inbox sends them: the answer is the text message, and GET /bookings/{booking_id}/messages lists the photo messages right after it, with their files. Once the text has reached the guest, the request answers 201 with it even if a photo was refused or its fate is unknown: check that list for the photos before sending them again. Whatever these limits, the hosting platform refuses a request body above 4.5 MB with a 413 that is not the JSON error of the API: send fewer or smaller photos per call.

**SMS are billed to the host**, €0.10 per segment, on their ZenHost subscription. When the subscription cannot be billed, the request answers sms_billing_unavailable: nothing is sent and nothing is billed.

Refusals known before sending answer 422 and send nothing: channel_unavailable (the chosen channel cannot reach the guest, try another one: on platform, the Sales Channel of the booking has no messaging, no conversation exists there yet, or the host must restore their connection to it; on email, the account has no sending address), missing_guest_contact (no email or phone for the chosen channel). When the send fails, delivery_failed tells in details.delivery_outcome whether the message certainly did not leave (not_sent: safe to send again) or its fate is unknown (unknown: check GET /bookings/{booking_id}/messages before sending again).

For Zenny, a message from your App is a reply of the host: a reply Zenny was preparing for this conversation is dropped, and a conversation Zenny handed over to the host is released. Your message never becomes Knowledge. A booking outside the Connection Scope answers not_found, exactly like a missing one. Counts against the send rate limit.

Parameters

Path parameters

  • booking_idstring (uuid)required

    Booking id.

Headers

  • Idempotency-Keystring

    Replaying the same key on the same App Connection within 24 hours answers what the first request did (the same message, or the same refusal) and sends nothing new. Reusing it with a different body answers idempotency_key_reused; while the first request is still sending, idempotency_key_in_use.

    at most 255 characters

Request body

application/jsonSendMessageRequest

A text to the guest of the booking.

  • channelstringrequired

    platform is the messaging of the Sales Channel of the booking (Airbnb, Booking.com…); email and sms reach the guest contact details ZenHost holds.

    One of: platform email sms

  • textstringrequired

    The message. Shortcodes require their corresponding read permission, including nested custom values: bookings.read (plus prices.read for amounts), guests.read, properties.read for title/currency, property_guide.read for guide/custom values, or lock_codes.read. Missing permission refuses the send with forbidden_permission. Portal credentials and invoice/payment links cannot be expanded by Apps.

    at most 10000 characters

  • subjectstring

    Email only. Shortcodes follow the same read-permission checks as the text. Without it, the email takes the name of the Property.

    at most 255 characters

Responses

201The message, sent.

application/jsonMessage

  • idstring (uuid)required
  • directionstringrequired

    inbound from the guest, outbound to the guest.

    One of: inbound outbound

  • authorMessageAuthorrequired

    Who wrote the message. Never carries a guest email or phone, nor the name of the team member.

    Show 2 child attributes
    • typestringrequired

      guest (inbound), host (the host or a team member), zenny (written by Zenny, the ZenHost assistant), automation (a Scheduled Message) or app (an App, see app_name). Version 1 may add values.

      One of: guest host zenny automation app

    • app_namestring

      Name of the App that sent the message, when type is app.

  • channelstringrequired

    platform is the messaging of the Sales Channel of the booking (Airbnb, Booking.com…). Version 1 may add values.

    One of: platform email sms

  • textstringrequired
  • subjectstring | nullrequired

    Email subject.

  • attachmentsMessageAttachment[]required
    Show 5 child attributes
    • indexintegerrequired

      Position of the file in the message, as in the download URL. Files that cannot be downloaded are left out, so indexes may skip.

      min 0

    • typestringrequired

      Only images in version 1; other types may be added.

      One of: image

    • file_namestring | nullrequired
    • content_typestring | nullrequired

      MIME type when known; the download answers with the actual one.

    • urlstring (uri)required

      Download URL of the file. Call it with the access token of the App Connection, like any other endpoint.

  • delivery_statusstringrequired

    received for an inbound message. For an outbound one: pending while it is not confirmed sent (in flight, or its fate is not known yet), sent, or rejected when it did not reach the guest: the Sales Channel refused it, or its send failed or stayed unconfirmed for a minute, as the ZenHost inbox shows it. Version 1 may add values.

    One of: received pending sent rejected

  • sent_atstring (date-time)required
  • created_atstring (date-time)required

    When ZenHost recorded the message; the list is sorted on it.

401Error code: unauthorized, connection_revoked.

Error codes

  • unauthorized The access token is missing, unknown, expired or revoked, or was issued before the account connected the App again. Refresh it; if refreshing fails, ask the owner to connect again.
  • connection_revoked The owner revoked the App Connection (or your App revoked its own refresh token). Stop calling for this account and drop its tokens.
402Error code: subscription_blocked.

Error codes

  • subscription_blocked The ZenHost subscription of the account is blocked (unpaid, cancelled…). The connection is kept: tell your customer, calls work again once the subscription is restored.
403Error code: app_suspended, forbidden_permission.

Error codes

  • app_suspended ZenHost suspended your App, or no longer allows it on this account. Stop calling and contact ZenHost.
  • forbidden_permission Your App was not granted the Permission this endpoint requires.
404Error code: not_found.

Error codes

  • not_found The resource does not exist or is outside the Connection Scope (both look the same), or the path is not an endpoint of /api/v1.
409Error code: idempotency_key_in_use.

Error codes

  • idempotency_key_in_use A request with this Idempotency-Key is still being processed. Retry in a few seconds to get its answer.
422Error code: validation_failed, idempotency_key_reused, channel_unavailable, missing_guest_contact, sms_billing_unavailable.

Error codes

  • validation_failed The query, headers or body are invalid; details.issues points at each problem (path, message, and maximum when a value or list is too big).
  • idempotency_key_reused This Idempotency-Key was already used on this App Connection with a different body.
  • channel_unavailable The chosen channel cannot reach the guest of this booking. On platform: the Sales Channel has no messaging for this booking, no conversation exists there yet, or the host must restore their connection to that Sales Channel. On email: the account has no sending address. Nothing was sent; try another channel.
  • missing_guest_contact The guest of this booking has no email address (for email) or phone number (for sms). Nothing was sent.
  • sms_billing_unavailable The ZenHost subscription of the account cannot be billed for SMS. Nothing was sent and nothing was billed; use another channel.
429Error code: rate_limited.

Header Retry-After — Seconds to wait before the next call is allowed. Limits per App Connection: 60 reads (GET), 10 writes (other POST) and 30 messages sent to guests per minute.

Error codes

  • rate_limited Too many calls on this App Connection. Wait for the number of seconds in Retry-After.
500Error code: internal_error.

Error codes

  • internal_error ZenHost failed to answer. Retry later with a back-off.
502Error code: delivery_failed.

Error codes

  • delivery_failed The message could not be delivered. details.delivery_outcome is not_sent when it certainly did not leave (safe to send again) or unknown when its fate is not known (read the messages of the booking before sending again).

Every error code and what to do