> 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/templates.md).

# Templates

Message templates.

## List message templates (paginated)

> Returns message templates that can be used as \`subject\`/\`message\` for POST /reservations/{id}/messages/email|sms. Required scope: \`templates.read\`.

```json
{"openapi":"3.0.0","info":{"title":"Public REST API v1 – mobile-calendar.com","version":"1.0.0"},"tags":[{"name":"templates","description":"Message templates."}],"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"}},"parameters":{"PageParam":{"name":"page","in":"query","description":"Page number (>=1)","required":false,"schema":{"type":"integer","default":1,"minimum":1}},"LimitParam":{"name":"limit","in":"query","description":"Page size (1–200)","required":false,"schema":{"type":"integer","default":25,"maximum":200,"minimum":1}}},"schemas":{"TemplateListResponse":{"required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Template"}},"meta":{"$ref":"#/components/schemas/MetaWithPagination"}},"type":"object"},"Template":{"description":"Message template. `subject` and `message` may contain `{tags}` and `[[dynamic_tags]]` that are replaced with reservation data when sending via POST /reservations/{id}/messages/email|sms. Use GET /template-tags for the list of available tags.","required":["templateId","templateName","subject","message","lang","lastEdit"],"properties":{"templateId":{"type":"integer"},"templateName":{"type":"string"},"subject":{"type":"string"},"message":{"description":"HTML body of the template.","type":"string"},"lang":{"description":"Language code (ISO 639-1)","type":"string"},"lastEdit":{"description":"Last modification time (UTC, ISO 8601) — same format as `addDate`/`editDate` of other resources.","type":"string","format":"date-time"}},"type":"object"},"MetaWithPagination":{"description":"Pagination parameters with request tracking in list responses.","required":["totalItems","currentPage","totalPages","itemsPerPage","ruid"],"properties":{"totalItems":{"type":"integer","minimum":0},"currentPage":{"type":"integer","minimum":1},"totalPages":{"type":"integer","minimum":0},"itemsPerPage":{"type":"integer","minimum":1},"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"}]},"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":{"/templates":{"get":{"tags":["templates"],"summary":"List message templates (paginated)","description":"Returns message templates that can be used as `subject`/`message` for POST /reservations/{id}/messages/email|sms. Required scope: `templates.read`.","operationId":"listTemplates","parameters":[{"$ref":"#/components/parameters/PageParam"},{"$ref":"#/components/parameters/LimitParam"},{"name":"search","in":"query","description":"Search in template name and subject","required":false,"schema":{"type":"string","maxLength":255}},{"name":"lang","in":"query","description":"Filter by template language (ISO 639-1)","required":false,"schema":{"type":"string"}},{"name":"orderBy","in":"query","description":"Sort field","required":false,"schema":{"type":"string","default":"templateId","enum":["templateId","templateName","lang","lastEdit"]}},{"name":"orderType","in":"query","description":"Sort direction","required":false,"schema":{"type":"string","default":"ASC","enum":["ASC","DESC"]}}],"responses":{"200":{"description":"List of templates","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateListResponse"}}}},"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","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem422"}}}}}}}}}
```

## Create message template

> Creates a message template. The HTML of \`message\` is sanitized on save (allowed formatting tags only; event handlers and unsafe URL schemes are removed), so the stored value may differ from the one sent — the response returns what was actually saved. Use GET /template-tags for the list of tags available in \`subject\` and \`message\`. Required scope: \`templates.create\`.

```json
{"openapi":"3.0.0","info":{"title":"Public REST API v1 – mobile-calendar.com","version":"1.0.0"},"tags":[{"name":"templates","description":"Message templates."}],"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":{"TemplateCreateRequest":{"description":"New message template. The HTML of `message` is sanitized on save: only formatting tags are kept and unsafe attributes (event handlers, `javascript:` URLs) are removed, so the stored value may differ from the one sent.","required":["templateName","subject","message","lang"],"properties":{"templateName":{"description":"Internal name of the template (not visible to the guest).","type":"string","maxLength":255},"subject":{"description":"Message subject. May contain tags.","type":"string","maxLength":255},"message":{"description":"HTML body of the template. May contain tags. The 65535-byte limit applies to the sanitized value that is stored: sanitizing wraps bare text in a paragraph, so a plain-text body is measured with those extra bytes included.","type":"string","maxLength":65535},"lang":{"description":"Language code (ISO 639-1)","type":"string","maxLength":5}},"type":"object"},"TemplateResponse":{"description":"Single template response with metadata","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/Template"},"meta":{"$ref":"#/components/schemas/MetaWithRuid"}},"type":"object"},"Template":{"description":"Message template. `subject` and `message` may contain `{tags}` and `[[dynamic_tags]]` that are replaced with reservation data when sending via POST /reservations/{id}/messages/email|sms. Use GET /template-tags for the list of available tags.","required":["templateId","templateName","subject","message","lang","lastEdit"],"properties":{"templateId":{"type":"integer"},"templateName":{"type":"string"},"subject":{"type":"string"},"message":{"description":"HTML body of the template.","type":"string"},"lang":{"description":"Language code (ISO 639-1)","type":"string"},"lastEdit":{"description":"Last modification time (UTC, ISO 8601) — same format as `addDate`/`editDate` of other resources.","type":"string","format":"date-time"}},"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":{"/templates":{"post":{"tags":["templates"],"summary":"Create message template","description":"Creates a message template. The HTML of `message` is sanitized on save (allowed formatting tags only; event handlers and unsafe URL schemes are removed), so the stored value may differ from the one sent — the response returns what was actually saved. Use GET /template-tags for the list of tags available in `subject` and `message`. Required scope: `templates.create`.","operationId":"createTemplate","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateCreateRequest"}}}},"responses":{"201":{"description":"Created","headers":{"Location":{"description":"URL of the new resource","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateResponse"}}}},"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","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem422"}}}}}}}}}
```

## Get message template by ID

> Required scope: \`templates.read\`.

```json
{"openapi":"3.0.0","info":{"title":"Public REST API v1 – mobile-calendar.com","version":"1.0.0"},"tags":[{"name":"templates","description":"Message templates."}],"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":{"TemplateResponse":{"description":"Single template response with metadata","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/Template"},"meta":{"$ref":"#/components/schemas/MetaWithRuid"}},"type":"object"},"Template":{"description":"Message template. `subject` and `message` may contain `{tags}` and `[[dynamic_tags]]` that are replaced with reservation data when sending via POST /reservations/{id}/messages/email|sms. Use GET /template-tags for the list of available tags.","required":["templateId","templateName","subject","message","lang","lastEdit"],"properties":{"templateId":{"type":"integer"},"templateName":{"type":"string"},"subject":{"type":"string"},"message":{"description":"HTML body of the template.","type":"string"},"lang":{"description":"Language code (ISO 639-1)","type":"string"},"lastEdit":{"description":"Last modification time (UTC, ISO 8601) — same format as `addDate`/`editDate` of other resources.","type":"string","format":"date-time"}},"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":{"/templates/{id}":{"get":{"tags":["templates"],"summary":"Get message template by ID","description":"Required scope: `templates.read`.","operationId":"getTemplate","parameters":[{"name":"id","in":"path","description":"Template ID","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateResponse"}}}},"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":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem404"}}}}}}}}}
```

## Delete message template

> Deletes a message template. Auto-message rules that still point to this template stop sending — check them before deleting. Required scope: \`templates.delete\`.

```json
{"openapi":"3.0.0","info":{"title":"Public REST API v1 – mobile-calendar.com","version":"1.0.0"},"tags":[{"name":"templates","description":"Message templates."}],"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":{"/templates/{id}":{"delete":{"tags":["templates"],"summary":"Delete message template","description":"Deletes a message template. Auto-message rules that still point to this template stop sending — check them before deleting. Required scope: `templates.delete`.","operationId":"deleteTemplate","parameters":[{"name":"id","in":"path","description":"Template ID","required":true,"schema":{"type":"integer"}}],"responses":{"204":{"description":"Deleted successfully","headers":{"RUID":{"description":"Request unique identifier","schema":{"type":"string"}}}},"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":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem404"}}}}}}}}}
```

## Update message template (partial update)

> Updates one or more fields of a template. Only the fields provided in the request body are changed; a field that is sent must not be null or empty. The HTML of \`message\` is sanitized on save. Required scope: \`templates.update\`.

```json
{"openapi":"3.0.0","info":{"title":"Public REST API v1 – mobile-calendar.com","version":"1.0.0"},"tags":[{"name":"templates","description":"Message templates."}],"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":{"TemplateUpdateRequest":{"description":"Partial update — only the fields present in the body are changed. A field that is sent must not be null or empty.","properties":{"templateName":{"type":"string","maxLength":255},"subject":{"type":"string","maxLength":255},"message":{"type":"string","maxLength":65535},"lang":{"type":"string","maxLength":5}},"type":"object"},"TemplateResponse":{"description":"Single template response with metadata","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/Template"},"meta":{"$ref":"#/components/schemas/MetaWithRuid"}},"type":"object"},"Template":{"description":"Message template. `subject` and `message` may contain `{tags}` and `[[dynamic_tags]]` that are replaced with reservation data when sending via POST /reservations/{id}/messages/email|sms. Use GET /template-tags for the list of available tags.","required":["templateId","templateName","subject","message","lang","lastEdit"],"properties":{"templateId":{"type":"integer"},"templateName":{"type":"string"},"subject":{"type":"string"},"message":{"description":"HTML body of the template.","type":"string"},"lang":{"description":"Language code (ISO 639-1)","type":"string"},"lastEdit":{"description":"Last modification time (UTC, ISO 8601) — same format as `addDate`/`editDate` of other resources.","type":"string","format":"date-time"}},"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":{"/templates/{id}":{"patch":{"tags":["templates"],"summary":"Update message template (partial update)","description":"Updates one or more fields of a template. Only the fields provided in the request body are changed; a field that is sent must not be null or empty. The HTML of `message` is sanitized on save. Required scope: `templates.update`.","operationId":"updateTemplate","parameters":[{"name":"id","in":"path","description":"Template ID","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateUpdateRequest"}}}},"responses":{"200":{"description":"Updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateResponse"}}}},"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":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem404"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem422"}}}}}}}}}
```

## List template tags (grouped and described)

> Returns every tag that can be placed in the \`subject\` or \`message\` of a template, grouped by area (reservation, guest, property, payment, …) and described.\
> \
> Two syntaxes are used: \`{tag}\` for values substituted from data, and \`\[\[tag]]\` for values the server has to resolve (links, calculated amounts). A tag whose value is unavailable — no reservation context, module not configured, payment link in an OTA chat — is replaced with an \*\*empty string\*\*, so the message is always sent.\
> \
> The list is static (it does not depend on account data). Required scope: \`templates.read\`.

```json
{"openapi":"3.0.0","info":{"title":"Public REST API v1 – mobile-calendar.com","version":"1.0.0"},"tags":[{"name":"templates","description":"Message templates."}],"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":{"TemplateTagListResponse":{"required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TemplateTagGroup"}},"meta":{"properties":{"totalGroups":{"type":"integer"},"totalTags":{"type":"integer"},"ruid":{"type":"string"}},"type":"object"}},"type":"object"},"TemplateTagGroup":{"description":"Group of related template tags.","required":["key","label","description","tags"],"properties":{"key":{"type":"string","enum":["reservation","meals","payment","paymentLinks","checkin","client","property"]},"label":{"type":"string"},"description":{"type":"string"},"tags":{"type":"array","items":{"$ref":"#/components/schemas/TemplateTag"}}},"type":"object"},"TemplateTag":{"description":"Single tag that can be placed in the subject or body of a template.","required":["tag","name","description","type","resolvedAt","requiresReservation","allowedInOtaChat"],"properties":{"tag":{"description":"Exact string to paste into the template.","type":"string"},"name":{"description":"Stable identifier of the tag.","type":"string"},"description":{"description":"What the tag is replaced with.","type":"string"},"type":{"description":"`static` — value substituted from data; `dynamic` — resolved by the server (link, calculated amount).","type":"string","enum":["static","dynamic"]},"resolvedAt":{"description":"`render` — resolved when the message is rendered; `send` — resolved only at the moment of sending (payment links).","type":"string","enum":["render","send"]},"requiresReservation":{"description":"Whether the tag needs a reservation context. Without it the tag resolves to an empty string.","type":"boolean"},"allowedInOtaChat":{"description":"Whether the tag may be used in Airbnb/Booking.com chat messages. Payment links are forbidden there and resolve to an empty string.","type":"boolean"}},"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":{"/template-tags":{"get":{"tags":["templates"],"summary":"List template tags (grouped and described)","description":"Returns every tag that can be placed in the `subject` or `message` of a template, grouped by area (reservation, guest, property, payment, …) and described.\n\nTwo syntaxes are used: `{tag}` for values substituted from data, and `[[tag]]` for values the server has to resolve (links, calculated amounts). A tag whose value is unavailable — no reservation context, module not configured, payment link in an OTA chat — is replaced with an **empty string**, so the message is always sent.\n\nThe list is static (it does not depend on account data). Required scope: `templates.read`.","operationId":"listTemplateTags","responses":{"200":{"description":"Grouped list of available template tags","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateTagListResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem401"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem403"}}}}}}}}}
```
