> For the complete documentation index, see [llms.txt](https://mobile-calendar.gitbook.io/v1/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://mobile-calendar.gitbook.io/v1/rest-api/auto-messages.md).

# Auto Messages

Automatic message rules (scheduled/instant e-mail, SMS and OTA chat messages).

## List automatic message rules

> Returns all automatic message rules of the account. Required scope: \`autoMessages.read\`.

```json
{"openapi":"3.0.0","info":{"title":"Public REST API v1 – mobile-calendar.com","version":"1.0.0"},"tags":[{"name":"auto-messages","description":"Automatic message rules (scheduled/instant e-mail, SMS and OTA chat messages)."}],"servers":[{"url":"https://api.mobile-calendar.com/v1/public","description":"Production"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","description":"Pass the token in header: Authorization: Bearer <JWT>","bearerFormat":"JWT","scheme":"bearer"}},"schemas":{"AutoMessageListResponse":{"required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AutoMessage"}},"meta":{"$ref":"#/components/schemas/MetaWithRuid"}},"type":"object"},"AutoMessage":{"description":"Automatic message rule.","required":["id","name","messageType","templateId","action","mode","guest","isEnabled","time"],"properties":{"id":{"type":"integer"},"name":{"type":"string"},"messageType":{"type":"array","items":{"type":"string","enum":["EMAIL","SMS","AIRBNB_CHAT","BOOKING_CHAT"]}},"templateId":{"type":"integer"},"action":{"type":"string"},"mode":{"description":"Derived from `action`.","type":"string","enum":["INSTANT","SCHEDULED"]},"dayOffset":{"type":"integer","nullable":true},"time":{"type":"string"},"guest":{"type":"boolean"},"custom":{"type":"boolean","nullable":true},"customEmail":{"type":"string","nullable":true},"customPhone":{"type":"string","nullable":true},"smtpId":{"type":"integer","nullable":true},"filterRooms":{"type":"array","items":{"type":"integer"},"nullable":true},"filterPaymentStatus":{"type":"array","items":{"type":"string"},"nullable":true},"filterSource":{"type":"array","items":{"type":"integer"},"nullable":true},"filterLanguages":{"type":"array","items":{"type":"string"},"nullable":true},"conditions":{"type":"array","items":{"$ref":"#/components/schemas/AutoMessageCondition"},"nullable":true},"isEnabled":{"type":"boolean"},"sendOverdue":{"type":"boolean"},"createdAt":{"description":"Creation time (UTC, ISO 8601).","type":"string","format":"date-time","nullable":true},"updatedAt":{"description":"Last modification time (UTC, ISO 8601); null until the rule is first updated.","type":"string","format":"date-time","nullable":true}},"type":"object"},"AutoMessageCondition":{"description":"Additional condition a reservation must meet for the rule to fire. Each field may appear at most once. Numeric fields (`days`, `price`) accept only the comparison operators `<`, `>`, `<=`, `>=`, `=`, `!=`; text fields (`phone`, `email`) accept only `startsWith`, `endsWith`, `contains`, `notContains`. Any other field/operator pair is rejected with 422.","required":["field","operator","value"],"properties":{"field":{"description":"`days` = length of stay in nights, `price` = reservation total (numeric fields). `phone` = guest phone number, `email` = guest e-mail address (text fields). The phone is compared after stripping spaces, dashes, dots and parentheses, and a leading `00` of the guest's number is treated as `+`, so `+48 600-700-800`, `0048600700800` and `+48600700800` are the same number. The condition value is a fragment of the number: formatting characters are ignored. A country prefix may be written as `+48` or `0048` with every operator (a value made of `00` followed by digits is tried both literally and as `+` followed by those digits, which can only match at the start of the number); a bare `00` is just two digits. The e-mail comparison is case-insensitive.","type":"string","enum":["days","price","phone","email"]},"operator":{"description":"`<`, `>`, `<=`, `>=`, `=`, `!=` — only for `days` and `price`. `startsWith`, `endsWith`, `contains`, `notContains` — only for `phone` and `email`. Guests without a phone number / e-mail address never match `startsWith`, `endsWith` or `contains` and always match `notContains`.","type":"string","enum":["<",">","<=",">=","=","!=","startsWith","endsWith","contains","notContains"]},"value":{"description":"Value compared using the operator. For `days`/`price`: a number. For `phone`/`email`: a non-empty string of at most 100 characters (for `phone` it must contain at least one digit or `+`)."}},"type":"object"},"MetaWithRuid":{"description":"Metadata with request tracking.","required":["ruid"],"properties":{"ruid":{"description":"Request Unique ID","type":"string","format":"uuid"}},"type":"object"},"ApiProblem401":{"description":"Missing authentication or invalid credentials.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"401 Unauthorized","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]},"ApiProblemBase":{"description":"RFC 7807 Problem Details (base schema).","required":["type","title","status","detail","instance"],"properties":{"type":{"description":"RFC 7807 base — DO NOT use directly in endpoints.\nIn endpoints reference ApiProblem400/401/403/409/422/429/500.","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"},"ApiProblem403":{"description":"Authenticated user but no access.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"403 Forbidden","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]}}},"paths":{"/auto-messages":{"get":{"tags":["auto-messages"],"summary":"List automatic message rules","description":"Returns all automatic message rules of the account. Required scope: `autoMessages.read`.","operationId":"listAutoMessages","responses":{"200":{"description":"List of automatic message rules","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutoMessageListResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem401"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem403"}}}}}}}}}
```

## Create automatic message rule

> Creates an automatic message rule (e-mail, SMS and/or OTA chat). \`mode\` and \`dayOffset\` are derived from \`action\` (see the request schema). EMAIL requires a verified SMTP account (\`smtpId\`), SMS requires SMS API configuration on the account. Chat types (AIRBNB\_CHAT/BOOKING\_CHAT) require \`filterSource\` to be exactly the source IDs of the selected chat channels, and the template must not contain payment link tags. Required scope: \`autoMessages.create\`.

```json
{"openapi":"3.0.0","info":{"title":"Public REST API v1 – mobile-calendar.com","version":"1.0.0"},"tags":[{"name":"auto-messages","description":"Automatic message rules (scheduled/instant e-mail, SMS and OTA chat messages)."}],"servers":[{"url":"https://api.mobile-calendar.com/v1/public","description":"Production"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","description":"Pass the token in header: Authorization: Bearer <JWT>","bearerFormat":"JWT","scheme":"bearer"}},"schemas":{"AutoMessageRequest":{"description":"Automatic message rule. `mode` and `dayOffset` are derived from `action`: instant actions (ADD, DELETE, CHANGE_TO_PREPAYMENT, CHANGE_TO_PAID_ALL, ONLINE_CHECK_IN_COMPLETED, AFTER_GENERATE_DOOR_CODE) ignore `dayOffset`; BEFORE_/AFTER_CHECK_IN/OUT require a positive `dayOffset` (number of days, direction comes from the action); CHECK_IN/CHECK_OUT use day 0; PREPAYMENT_DEADLINE accepts any integer. Chat types (AIRBNB_CHAT/BOOKING_CHAT) require `filterSource` to be exactly the source IDs of the selected chat channels and reject templates containing payment link tags.","required":["name","messageType","templateId","action","guest","custom","filterRooms","filterPaymentStatus","filterSource","filterLanguages","conditions","time"],"properties":{"name":{"type":"string","maxLength":255},"messageType":{"description":"Channels the rule sends to (one message per selected channel).","type":"array","items":{"type":"string","enum":["EMAIL","SMS","AIRBNB_CHAT","BOOKING_CHAT"]}},"templateId":{"description":"Message template (see GET /templates).","type":"integer"},"action":{"type":"string","enum":["ADD","DELETE","BEFORE_CHECK_IN","CHECK_IN","AFTER_CHECK_IN","BEFORE_CHECK_OUT","CHECK_OUT","AFTER_CHECK_OUT","PREPAYMENT_DEADLINE","CHANGE_TO_PREPAYMENT","CHANGE_TO_PAID_ALL","ONLINE_CHECK_IN_COMPLETED","AFTER_GENERATE_DOOR_CODE"]},"dayOffset":{"description":"Days relative to the action (always positive for BEFORE_/AFTER_ actions; PREPAYMENT_DEADLINE accepts negative). Ignored for instant actions.","type":"integer","nullable":true},"time":{"description":"Full hour (HH:00) at which scheduled rules fire.","type":"string","enum":["00:00","01:00","02:00","03:00","04:00","05:00","06:00","07:00","08:00","09:00","10:00","11:00","12:00","13:00","14:00","15:00","16:00","17:00","18:00","19:00","20:00","21:00","22:00","23:00"]},"guest":{"description":"Send to the reservation guest. When false, `customEmail`/`customPhone` receive the message instead (at least one required).","type":"boolean"},"custom":{"description":"Also send a copy to `customEmail`/`customPhone`.","type":"boolean"},"customEmail":{"type":"string","format":"email","nullable":true},"customPhone":{"type":"string","nullable":true},"smtpId":{"description":"Verified SMTP account — required when `messageType` contains EMAIL.","type":"integer","nullable":true},"filterRooms":{"description":"Limit to rooms (empty = all).","type":"array","items":{"type":"integer"}},"filterPaymentStatus":{"description":"Limit to payment statuses (empty = all).","type":"array","items":{"type":"string"}},"filterSource":{"description":"Limit to reservation sources (empty = all; forced for chat types).","type":"array","items":{"type":"integer"}},"filterLanguages":{"description":"Limit to client languages, ISO codes (empty = all).","type":"array","items":{"type":"string"}},"conditions":{"description":"Additional conditions (empty = none).","type":"array","items":{"$ref":"#/components/schemas/AutoMessageCondition"}},"isEnabled":{"type":"boolean","default":true},"sendOverdue":{"description":"For BEFORE_CHECK_IN/CHECK_IN rules: also send when a last-minute reservation is created after the rule's scheduled moment already passed.","type":"boolean","default":false}},"type":"object"},"AutoMessageCondition":{"description":"Additional condition a reservation must meet for the rule to fire. Each field may appear at most once. Numeric fields (`days`, `price`) accept only the comparison operators `<`, `>`, `<=`, `>=`, `=`, `!=`; text fields (`phone`, `email`) accept only `startsWith`, `endsWith`, `contains`, `notContains`. Any other field/operator pair is rejected with 422.","required":["field","operator","value"],"properties":{"field":{"description":"`days` = length of stay in nights, `price` = reservation total (numeric fields). `phone` = guest phone number, `email` = guest e-mail address (text fields). The phone is compared after stripping spaces, dashes, dots and parentheses, and a leading `00` of the guest's number is treated as `+`, so `+48 600-700-800`, `0048600700800` and `+48600700800` are the same number. The condition value is a fragment of the number: formatting characters are ignored. A country prefix may be written as `+48` or `0048` with every operator (a value made of `00` followed by digits is tried both literally and as `+` followed by those digits, which can only match at the start of the number); a bare `00` is just two digits. The e-mail comparison is case-insensitive.","type":"string","enum":["days","price","phone","email"]},"operator":{"description":"`<`, `>`, `<=`, `>=`, `=`, `!=` — only for `days` and `price`. `startsWith`, `endsWith`, `contains`, `notContains` — only for `phone` and `email`. Guests without a phone number / e-mail address never match `startsWith`, `endsWith` or `contains` and always match `notContains`.","type":"string","enum":["<",">","<=",">=","=","!=","startsWith","endsWith","contains","notContains"]},"value":{"description":"Value compared using the operator. For `days`/`price`: a number. For `phone`/`email`: a non-empty string of at most 100 characters (for `phone` it must contain at least one digit or `+`)."}},"type":"object"},"AutoMessageResponse":{"required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/AutoMessage"},"meta":{"$ref":"#/components/schemas/MetaWithRuid"}},"type":"object"},"AutoMessage":{"description":"Automatic message rule.","required":["id","name","messageType","templateId","action","mode","guest","isEnabled","time"],"properties":{"id":{"type":"integer"},"name":{"type":"string"},"messageType":{"type":"array","items":{"type":"string","enum":["EMAIL","SMS","AIRBNB_CHAT","BOOKING_CHAT"]}},"templateId":{"type":"integer"},"action":{"type":"string"},"mode":{"description":"Derived from `action`.","type":"string","enum":["INSTANT","SCHEDULED"]},"dayOffset":{"type":"integer","nullable":true},"time":{"type":"string"},"guest":{"type":"boolean"},"custom":{"type":"boolean","nullable":true},"customEmail":{"type":"string","nullable":true},"customPhone":{"type":"string","nullable":true},"smtpId":{"type":"integer","nullable":true},"filterRooms":{"type":"array","items":{"type":"integer"},"nullable":true},"filterPaymentStatus":{"type":"array","items":{"type":"string"},"nullable":true},"filterSource":{"type":"array","items":{"type":"integer"},"nullable":true},"filterLanguages":{"type":"array","items":{"type":"string"},"nullable":true},"conditions":{"type":"array","items":{"$ref":"#/components/schemas/AutoMessageCondition"},"nullable":true},"isEnabled":{"type":"boolean"},"sendOverdue":{"type":"boolean"},"createdAt":{"description":"Creation time (UTC, ISO 8601).","type":"string","format":"date-time","nullable":true},"updatedAt":{"description":"Last modification time (UTC, ISO 8601); null until the rule is first updated.","type":"string","format":"date-time","nullable":true}},"type":"object"},"MetaWithRuid":{"description":"Metadata with request tracking.","required":["ruid"],"properties":{"ruid":{"description":"Request Unique ID","type":"string","format":"uuid"}},"type":"object"},"ApiProblem400":{"description":"Request syntax/format error.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"400 Bad Request","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]},"ApiProblemBase":{"description":"RFC 7807 Problem Details (base schema).","required":["type","title","status","detail","instance"],"properties":{"type":{"description":"RFC 7807 base — DO NOT use directly in endpoints.\nIn endpoints reference ApiProblem400/401/403/409/422/429/500.","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"},"ApiProblem401":{"description":"Missing authentication or invalid credentials.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"401 Unauthorized","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]},"ApiProblem403":{"description":"Authenticated user but no access.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"403 Forbidden","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]},"ApiProblem422":{"description":"Input data validation error.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"422 Unprocessable Entity (validation)","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"},"errors":{"description":"Map: field name → error message(s)","type":"object","additionalProperties":{"$ref":"#/components/schemas/ErrorValue"}}},"type":"object"}]},"ErrorValue":{"description":"Single error message or list of messages.","oneOf":[{"description":"Error value in error map can be:\n- single string, or\n- array of strings (multiple messages for one field).","type":"string"},{"type":"array","items":{"type":"string"}}]}}},"paths":{"/auto-messages":{"post":{"tags":["auto-messages"],"summary":"Create automatic message rule","description":"Creates an automatic message rule (e-mail, SMS and/or OTA chat). `mode` and `dayOffset` are derived from `action` (see the request schema). EMAIL requires a verified SMTP account (`smtpId`), SMS requires SMS API configuration on the account. Chat types (AIRBNB_CHAT/BOOKING_CHAT) require `filterSource` to be exactly the source IDs of the selected chat channels, and the template must not contain payment link tags. Required scope: `autoMessages.create`.","operationId":"createAutoMessage","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutoMessageRequest"}}}},"responses":{"201":{"description":"Rule created (Location header points to the new resource)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutoMessageResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem400"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem401"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem403"}}}},"422":{"description":"Validation error (unknown action/time, SMTP_NOT_FOUND, SMTP_NOT_VERIFIED, SMS_GATEWAY_NOT_SET, TEMPLATE_NOT_FOUND, CHAT_FILTER_SOURCE_INVALID, PAYLINK_NOT_ALLOWED_IN_OTA_CHAT, ROOM_NOT_FOUND, SOURCE_NOT_FOUND, LANGUAGE_NOT_FOUND, CONDITIONS_NOT_VALID, etc.)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem422"}}}}}}}}}
```

## Get automatic message rule

> Returns a single automatic message rule. Required scope: \`autoMessages.read\`.

```json
{"openapi":"3.0.0","info":{"title":"Public REST API v1 – mobile-calendar.com","version":"1.0.0"},"tags":[{"name":"auto-messages","description":"Automatic message rules (scheduled/instant e-mail, SMS and OTA chat messages)."}],"servers":[{"url":"https://api.mobile-calendar.com/v1/public","description":"Production"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","description":"Pass the token in header: Authorization: Bearer <JWT>","bearerFormat":"JWT","scheme":"bearer"}},"schemas":{"AutoMessageResponse":{"required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/AutoMessage"},"meta":{"$ref":"#/components/schemas/MetaWithRuid"}},"type":"object"},"AutoMessage":{"description":"Automatic message rule.","required":["id","name","messageType","templateId","action","mode","guest","isEnabled","time"],"properties":{"id":{"type":"integer"},"name":{"type":"string"},"messageType":{"type":"array","items":{"type":"string","enum":["EMAIL","SMS","AIRBNB_CHAT","BOOKING_CHAT"]}},"templateId":{"type":"integer"},"action":{"type":"string"},"mode":{"description":"Derived from `action`.","type":"string","enum":["INSTANT","SCHEDULED"]},"dayOffset":{"type":"integer","nullable":true},"time":{"type":"string"},"guest":{"type":"boolean"},"custom":{"type":"boolean","nullable":true},"customEmail":{"type":"string","nullable":true},"customPhone":{"type":"string","nullable":true},"smtpId":{"type":"integer","nullable":true},"filterRooms":{"type":"array","items":{"type":"integer"},"nullable":true},"filterPaymentStatus":{"type":"array","items":{"type":"string"},"nullable":true},"filterSource":{"type":"array","items":{"type":"integer"},"nullable":true},"filterLanguages":{"type":"array","items":{"type":"string"},"nullable":true},"conditions":{"type":"array","items":{"$ref":"#/components/schemas/AutoMessageCondition"},"nullable":true},"isEnabled":{"type":"boolean"},"sendOverdue":{"type":"boolean"},"createdAt":{"description":"Creation time (UTC, ISO 8601).","type":"string","format":"date-time","nullable":true},"updatedAt":{"description":"Last modification time (UTC, ISO 8601); null until the rule is first updated.","type":"string","format":"date-time","nullable":true}},"type":"object"},"AutoMessageCondition":{"description":"Additional condition a reservation must meet for the rule to fire. Each field may appear at most once. Numeric fields (`days`, `price`) accept only the comparison operators `<`, `>`, `<=`, `>=`, `=`, `!=`; text fields (`phone`, `email`) accept only `startsWith`, `endsWith`, `contains`, `notContains`. Any other field/operator pair is rejected with 422.","required":["field","operator","value"],"properties":{"field":{"description":"`days` = length of stay in nights, `price` = reservation total (numeric fields). `phone` = guest phone number, `email` = guest e-mail address (text fields). The phone is compared after stripping spaces, dashes, dots and parentheses, and a leading `00` of the guest's number is treated as `+`, so `+48 600-700-800`, `0048600700800` and `+48600700800` are the same number. The condition value is a fragment of the number: formatting characters are ignored. A country prefix may be written as `+48` or `0048` with every operator (a value made of `00` followed by digits is tried both literally and as `+` followed by those digits, which can only match at the start of the number); a bare `00` is just two digits. The e-mail comparison is case-insensitive.","type":"string","enum":["days","price","phone","email"]},"operator":{"description":"`<`, `>`, `<=`, `>=`, `=`, `!=` — only for `days` and `price`. `startsWith`, `endsWith`, `contains`, `notContains` — only for `phone` and `email`. Guests without a phone number / e-mail address never match `startsWith`, `endsWith` or `contains` and always match `notContains`.","type":"string","enum":["<",">","<=",">=","=","!=","startsWith","endsWith","contains","notContains"]},"value":{"description":"Value compared using the operator. For `days`/`price`: a number. For `phone`/`email`: a non-empty string of at most 100 characters (for `phone` it must contain at least one digit or `+`)."}},"type":"object"},"MetaWithRuid":{"description":"Metadata with request tracking.","required":["ruid"],"properties":{"ruid":{"description":"Request Unique ID","type":"string","format":"uuid"}},"type":"object"},"ApiProblem401":{"description":"Missing authentication or invalid credentials.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"401 Unauthorized","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]},"ApiProblemBase":{"description":"RFC 7807 Problem Details (base schema).","required":["type","title","status","detail","instance"],"properties":{"type":{"description":"RFC 7807 base — DO NOT use directly in endpoints.\nIn endpoints reference ApiProblem400/401/403/409/422/429/500.","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"},"ApiProblem403":{"description":"Authenticated user but no access.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"403 Forbidden","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]},"ApiProblem404":{"description":"Resource specified in the request was not found.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"404 Not Found","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]}}},"paths":{"/auto-messages/{id}":{"get":{"tags":["auto-messages"],"summary":"Get automatic message rule","description":"Returns a single automatic message rule. Required scope: `autoMessages.read`.","operationId":"getAutoMessage","parameters":[{"name":"id","in":"path","description":"AutoMessage rule ID","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Automatic message rule","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutoMessageResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem401"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem403"}}}},"404":{"description":"Rule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem404"}}}}}}}}}
```

## Update automatic message rule

> Full update of an automatic message rule — the same payload and validation as create. Required scope: \`autoMessages.update\`.

```json
{"openapi":"3.0.0","info":{"title":"Public REST API v1 – mobile-calendar.com","version":"1.0.0"},"tags":[{"name":"auto-messages","description":"Automatic message rules (scheduled/instant e-mail, SMS and OTA chat messages)."}],"servers":[{"url":"https://api.mobile-calendar.com/v1/public","description":"Production"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","description":"Pass the token in header: Authorization: Bearer <JWT>","bearerFormat":"JWT","scheme":"bearer"}},"schemas":{"AutoMessageRequest":{"description":"Automatic message rule. `mode` and `dayOffset` are derived from `action`: instant actions (ADD, DELETE, CHANGE_TO_PREPAYMENT, CHANGE_TO_PAID_ALL, ONLINE_CHECK_IN_COMPLETED, AFTER_GENERATE_DOOR_CODE) ignore `dayOffset`; BEFORE_/AFTER_CHECK_IN/OUT require a positive `dayOffset` (number of days, direction comes from the action); CHECK_IN/CHECK_OUT use day 0; PREPAYMENT_DEADLINE accepts any integer. Chat types (AIRBNB_CHAT/BOOKING_CHAT) require `filterSource` to be exactly the source IDs of the selected chat channels and reject templates containing payment link tags.","required":["name","messageType","templateId","action","guest","custom","filterRooms","filterPaymentStatus","filterSource","filterLanguages","conditions","time"],"properties":{"name":{"type":"string","maxLength":255},"messageType":{"description":"Channels the rule sends to (one message per selected channel).","type":"array","items":{"type":"string","enum":["EMAIL","SMS","AIRBNB_CHAT","BOOKING_CHAT"]}},"templateId":{"description":"Message template (see GET /templates).","type":"integer"},"action":{"type":"string","enum":["ADD","DELETE","BEFORE_CHECK_IN","CHECK_IN","AFTER_CHECK_IN","BEFORE_CHECK_OUT","CHECK_OUT","AFTER_CHECK_OUT","PREPAYMENT_DEADLINE","CHANGE_TO_PREPAYMENT","CHANGE_TO_PAID_ALL","ONLINE_CHECK_IN_COMPLETED","AFTER_GENERATE_DOOR_CODE"]},"dayOffset":{"description":"Days relative to the action (always positive for BEFORE_/AFTER_ actions; PREPAYMENT_DEADLINE accepts negative). Ignored for instant actions.","type":"integer","nullable":true},"time":{"description":"Full hour (HH:00) at which scheduled rules fire.","type":"string","enum":["00:00","01:00","02:00","03:00","04:00","05:00","06:00","07:00","08:00","09:00","10:00","11:00","12:00","13:00","14:00","15:00","16:00","17:00","18:00","19:00","20:00","21:00","22:00","23:00"]},"guest":{"description":"Send to the reservation guest. When false, `customEmail`/`customPhone` receive the message instead (at least one required).","type":"boolean"},"custom":{"description":"Also send a copy to `customEmail`/`customPhone`.","type":"boolean"},"customEmail":{"type":"string","format":"email","nullable":true},"customPhone":{"type":"string","nullable":true},"smtpId":{"description":"Verified SMTP account — required when `messageType` contains EMAIL.","type":"integer","nullable":true},"filterRooms":{"description":"Limit to rooms (empty = all).","type":"array","items":{"type":"integer"}},"filterPaymentStatus":{"description":"Limit to payment statuses (empty = all).","type":"array","items":{"type":"string"}},"filterSource":{"description":"Limit to reservation sources (empty = all; forced for chat types).","type":"array","items":{"type":"integer"}},"filterLanguages":{"description":"Limit to client languages, ISO codes (empty = all).","type":"array","items":{"type":"string"}},"conditions":{"description":"Additional conditions (empty = none).","type":"array","items":{"$ref":"#/components/schemas/AutoMessageCondition"}},"isEnabled":{"type":"boolean","default":true},"sendOverdue":{"description":"For BEFORE_CHECK_IN/CHECK_IN rules: also send when a last-minute reservation is created after the rule's scheduled moment already passed.","type":"boolean","default":false}},"type":"object"},"AutoMessageCondition":{"description":"Additional condition a reservation must meet for the rule to fire. Each field may appear at most once. Numeric fields (`days`, `price`) accept only the comparison operators `<`, `>`, `<=`, `>=`, `=`, `!=`; text fields (`phone`, `email`) accept only `startsWith`, `endsWith`, `contains`, `notContains`. Any other field/operator pair is rejected with 422.","required":["field","operator","value"],"properties":{"field":{"description":"`days` = length of stay in nights, `price` = reservation total (numeric fields). `phone` = guest phone number, `email` = guest e-mail address (text fields). The phone is compared after stripping spaces, dashes, dots and parentheses, and a leading `00` of the guest's number is treated as `+`, so `+48 600-700-800`, `0048600700800` and `+48600700800` are the same number. The condition value is a fragment of the number: formatting characters are ignored. A country prefix may be written as `+48` or `0048` with every operator (a value made of `00` followed by digits is tried both literally and as `+` followed by those digits, which can only match at the start of the number); a bare `00` is just two digits. The e-mail comparison is case-insensitive.","type":"string","enum":["days","price","phone","email"]},"operator":{"description":"`<`, `>`, `<=`, `>=`, `=`, `!=` — only for `days` and `price`. `startsWith`, `endsWith`, `contains`, `notContains` — only for `phone` and `email`. Guests without a phone number / e-mail address never match `startsWith`, `endsWith` or `contains` and always match `notContains`.","type":"string","enum":["<",">","<=",">=","=","!=","startsWith","endsWith","contains","notContains"]},"value":{"description":"Value compared using the operator. For `days`/`price`: a number. For `phone`/`email`: a non-empty string of at most 100 characters (for `phone` it must contain at least one digit or `+`)."}},"type":"object"},"AutoMessageResponse":{"required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/AutoMessage"},"meta":{"$ref":"#/components/schemas/MetaWithRuid"}},"type":"object"},"AutoMessage":{"description":"Automatic message rule.","required":["id","name","messageType","templateId","action","mode","guest","isEnabled","time"],"properties":{"id":{"type":"integer"},"name":{"type":"string"},"messageType":{"type":"array","items":{"type":"string","enum":["EMAIL","SMS","AIRBNB_CHAT","BOOKING_CHAT"]}},"templateId":{"type":"integer"},"action":{"type":"string"},"mode":{"description":"Derived from `action`.","type":"string","enum":["INSTANT","SCHEDULED"]},"dayOffset":{"type":"integer","nullable":true},"time":{"type":"string"},"guest":{"type":"boolean"},"custom":{"type":"boolean","nullable":true},"customEmail":{"type":"string","nullable":true},"customPhone":{"type":"string","nullable":true},"smtpId":{"type":"integer","nullable":true},"filterRooms":{"type":"array","items":{"type":"integer"},"nullable":true},"filterPaymentStatus":{"type":"array","items":{"type":"string"},"nullable":true},"filterSource":{"type":"array","items":{"type":"integer"},"nullable":true},"filterLanguages":{"type":"array","items":{"type":"string"},"nullable":true},"conditions":{"type":"array","items":{"$ref":"#/components/schemas/AutoMessageCondition"},"nullable":true},"isEnabled":{"type":"boolean"},"sendOverdue":{"type":"boolean"},"createdAt":{"description":"Creation time (UTC, ISO 8601).","type":"string","format":"date-time","nullable":true},"updatedAt":{"description":"Last modification time (UTC, ISO 8601); null until the rule is first updated.","type":"string","format":"date-time","nullable":true}},"type":"object"},"MetaWithRuid":{"description":"Metadata with request tracking.","required":["ruid"],"properties":{"ruid":{"description":"Request Unique ID","type":"string","format":"uuid"}},"type":"object"},"ApiProblem400":{"description":"Request syntax/format error.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"400 Bad Request","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]},"ApiProblemBase":{"description":"RFC 7807 Problem Details (base schema).","required":["type","title","status","detail","instance"],"properties":{"type":{"description":"RFC 7807 base — DO NOT use directly in endpoints.\nIn endpoints reference ApiProblem400/401/403/409/422/429/500.","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"},"ApiProblem401":{"description":"Missing authentication or invalid credentials.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"401 Unauthorized","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]},"ApiProblem403":{"description":"Authenticated user but no access.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"403 Forbidden","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]},"ApiProblem404":{"description":"Resource specified in the request was not found.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"404 Not Found","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]},"ApiProblem422":{"description":"Input data validation error.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"422 Unprocessable Entity (validation)","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"},"errors":{"description":"Map: field name → error message(s)","type":"object","additionalProperties":{"$ref":"#/components/schemas/ErrorValue"}}},"type":"object"}]},"ErrorValue":{"description":"Single error message or list of messages.","oneOf":[{"description":"Error value in error map can be:\n- single string, or\n- array of strings (multiple messages for one field).","type":"string"},{"type":"array","items":{"type":"string"}}]}}},"paths":{"/auto-messages/{id}":{"put":{"tags":["auto-messages"],"summary":"Update automatic message rule","description":"Full update of an automatic message rule — the same payload and validation as create. Required scope: `autoMessages.update`.","operationId":"updateAutoMessage","parameters":[{"name":"id","in":"path","description":"AutoMessage rule ID","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutoMessageRequest"}}}},"responses":{"200":{"description":"Updated rule","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutoMessageResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem400"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem401"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem403"}}}},"404":{"description":"Rule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem404"}}}},"422":{"description":"Validation error (same error codes as create)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem422"}}}}}}}}}
```

## Delete automatic message rule

> Permanently deletes the rule. Required scope: \`autoMessages.delete\`.

```json
{"openapi":"3.0.0","info":{"title":"Public REST API v1 – mobile-calendar.com","version":"1.0.0"},"tags":[{"name":"auto-messages","description":"Automatic message rules (scheduled/instant e-mail, SMS and OTA chat messages)."}],"servers":[{"url":"https://api.mobile-calendar.com/v1/public","description":"Production"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","description":"Pass the token in header: Authorization: Bearer <JWT>","bearerFormat":"JWT","scheme":"bearer"}},"schemas":{"ApiProblem401":{"description":"Missing authentication or invalid credentials.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"401 Unauthorized","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]},"ApiProblemBase":{"description":"RFC 7807 Problem Details (base schema).","required":["type","title","status","detail","instance"],"properties":{"type":{"description":"RFC 7807 base — DO NOT use directly in endpoints.\nIn endpoints reference ApiProblem400/401/403/409/422/429/500.","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"},"ApiProblem403":{"description":"Authenticated user but no access.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"403 Forbidden","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]},"ApiProblem404":{"description":"Resource specified in the request was not found.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"404 Not Found","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]}}},"paths":{"/auto-messages/{id}":{"delete":{"tags":["auto-messages"],"summary":"Delete automatic message rule","description":"Permanently deletes the rule. Required scope: `autoMessages.delete`.","operationId":"deleteAutoMessage","parameters":[{"name":"id","in":"path","description":"AutoMessage rule ID","required":true,"schema":{"type":"integer"}}],"responses":{"204":{"description":"Rule deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem401"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem403"}}}},"404":{"description":"Rule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem404"}}}}}}}}}
```

## Enable or disable automatic message rule

> Toggles the rule without touching its definition. Required scope: \`autoMessages.update\`.

```json
{"openapi":"3.0.0","info":{"title":"Public REST API v1 – mobile-calendar.com","version":"1.0.0"},"tags":[{"name":"auto-messages","description":"Automatic message rules (scheduled/instant e-mail, SMS and OTA chat messages)."}],"servers":[{"url":"https://api.mobile-calendar.com/v1/public","description":"Production"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","description":"Pass the token in header: Authorization: Bearer <JWT>","bearerFormat":"JWT","scheme":"bearer"}},"schemas":{"AutoMessageStatusRequest":{"required":["isEnabled"],"properties":{"isEnabled":{"type":"boolean"}},"type":"object"},"AutoMessageStatusResponse":{"required":["data","meta"],"properties":{"data":{"required":["id","isEnabled"],"properties":{"id":{"type":"integer"},"isEnabled":{"type":"boolean"}},"type":"object"},"meta":{"$ref":"#/components/schemas/MetaWithRuid"}},"type":"object"},"MetaWithRuid":{"description":"Metadata with request tracking.","required":["ruid"],"properties":{"ruid":{"description":"Request Unique ID","type":"string","format":"uuid"}},"type":"object"},"ApiProblem400":{"description":"Request syntax/format error.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"400 Bad Request","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]},"ApiProblemBase":{"description":"RFC 7807 Problem Details (base schema).","required":["type","title","status","detail","instance"],"properties":{"type":{"description":"RFC 7807 base — DO NOT use directly in endpoints.\nIn endpoints reference ApiProblem400/401/403/409/422/429/500.","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"},"ApiProblem401":{"description":"Missing authentication or invalid credentials.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"401 Unauthorized","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]},"ApiProblem403":{"description":"Authenticated user but no access.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"403 Forbidden","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]},"ApiProblem404":{"description":"Resource specified in the request was not found.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"404 Not Found","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]},"ApiProblem422":{"description":"Input data validation error.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"422 Unprocessable Entity (validation)","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"},"errors":{"description":"Map: field name → error message(s)","type":"object","additionalProperties":{"$ref":"#/components/schemas/ErrorValue"}}},"type":"object"}]},"ErrorValue":{"description":"Single error message or list of messages.","oneOf":[{"description":"Error value in error map can be:\n- single string, or\n- array of strings (multiple messages for one field).","type":"string"},{"type":"array","items":{"type":"string"}}]}}},"paths":{"/auto-messages/{id}/status":{"patch":{"tags":["auto-messages"],"summary":"Enable or disable automatic message rule","description":"Toggles the rule without touching its definition. Required scope: `autoMessages.update`.","operationId":"setAutoMessageStatus","parameters":[{"name":"id","in":"path","description":"AutoMessage rule ID","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutoMessageStatusRequest"}}}},"responses":{"200":{"description":"Status changed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutoMessageStatusResponse"}}}},"400":{"description":"Bad request (empty body)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem400"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem401"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem403"}}}},"404":{"description":"Rule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem404"}}}},"422":{"description":"Validation error (missing isEnabled)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem422"}}}}}}}}}
```
