Replace a template's working copy
Replaces the template’s WORKING COPY. It deliberately does not touch the published version, so a campaign that already sent keeps resolving to the copy it sent; what you change here is what the NEXT publish will contain. A FULL REPLACE, WHICH IS WHY IT IS PUT. An omitted key is cleared, not kept, so all four fields are required and a missing one is a 400 naming it. On an sms or push template send "" for subject and html_body. channel is refused by name: a template’s channel is fixed at creation, and changing it would leave an HTML body on a surface that renders plain text. THERE IS NO PRECONDITION ON THIS WRITE. updated_at is published so you can detect that the merchant’s dashboard changed the template under you, but the last writer wins. If two systems author the same template, coordinate on your side.
Authorizations
A secret API key. Publishable keys cannot reach this API. A key may carry an expiry, and an expired key is refused exactly like an unknown one, with a 401 that names no reason; check the key's expires_at in the dashboard rather than inferring it from a response. When a merchant rolls a key's secret they choose a grace window of up to 3 days, and for its duration BOTH the new secret and the one it replaced authenticate, so an integration moves over on its own deploy schedule instead of at the instant the button is pressed. Move before the window closes: after it, the old secret is refused. Nothing else about this contract moves with a roll. The key keeps its id and its scopes, so the only thing an integration updates is the credential itself.
Headers
A unique key per logical write. Replaying a request with the same key returns the first response byte for byte instead of applying the write twice.
Path Parameters
Body
EVERY FIELD IS REQUIRED because this is a full replace: an omitted key is cleared, not kept. A client that dropped text_body would blank the plain-text alternative of the merchant's email, the next publish would snapshot the half-template, and the send would still go out with every call answering 200. Empty strings are legal and are how a non-email template says "no subject, no html". null is not: send "" to clear a field. channel is refused by name. A template's channel is fixed at creation, and changing it would leave an html body on a surface that renders plain text.
Still unique per store; a clash is 409 name_taken.
Email only. Send "" on an sms or push template; a non-empty value there is 400 subject_not_allowed.
Email only, stored verbatim. Send "" on an sms or push template; a non-empty value there is 400 html_not_allowed.
Stored verbatim. Same closed merge-tag vocabulary as the create, so a body carrying an unknown tag is refused rather than delivered with a hole in it.
Response
Success
