Emails
Update Email Blocks
Replace an email body or mutate an existing block type.
PATCH
/
api
/
v1
/
emails
/
{emailId}
/
blocks
Update Email Blocks
curl --request PATCH \
--url https://api.sequenzy.com/api/v1/emails/{emailId}/blocks \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"html": "<string>",
"blocks": [
{}
],
"blockId": "<string>",
"type": "<string>",
"content": "<string>"
}
'import requests
url = "https://api.sequenzy.com/api/v1/emails/{emailId}/blocks"
payload = {
"html": "<string>",
"blocks": [{}],
"blockId": "<string>",
"type": "<string>",
"content": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
html: '<string>',
blocks: [{}],
blockId: '<string>',
type: '<string>',
content: '<string>'
})
};
fetch('https://api.sequenzy.com/api/v1/emails/{emailId}/blocks', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.sequenzy.com/api/v1/emails/{emailId}/blocks",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'html' => '<string>',
'blocks' => [
[
]
],
'blockId' => '<string>',
'type' => '<string>',
'content' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.sequenzy.com/api/v1/emails/{emailId}/blocks"
payload := strings.NewReader("{\n \"html\": \"<string>\",\n \"blocks\": [\n {}\n ],\n \"blockId\": \"<string>\",\n \"type\": \"<string>\",\n \"content\": \"<string>\"\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.patch("https://api.sequenzy.com/api/v1/emails/{emailId}/blocks")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"html\": \"<string>\",\n \"blocks\": [\n {}\n ],\n \"blockId\": \"<string>\",\n \"type\": \"<string>\",\n \"content\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sequenzy.com/api/v1/emails/{emailId}/blocks")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"html\": \"<string>\",\n \"blocks\": [\n {}\n ],\n \"blockId\": \"<string>\",\n \"type\": \"<string>\",\n \"content\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"email": {
"id": "email_123",
"companyId": "company_123",
"name": "Welcome",
"subject": "Welcome",
"previewText": null,
"blocks": [{ "id": "legacy-block", "type": "html", "content": "<table>...</table>" }],
"createdAt": "2026-04-19T12:00:00.000Z",
"updatedAt": "2026-04-19T12:05:00.000Z"
}
}
{
"success": true,
"email": {
"id": "email_123",
"companyId": "company_123",
"name": "Welcome",
"subject": "Welcome",
"previewText": null,
"blocks": [
{
"id": "cta",
"type": "button",
"text": "Buy now",
"url": "https://example.com",
"variant": "primary"
}
],
"createdAt": "2026-04-19T12:00:00.000Z",
"updatedAt": "2026-04-19T12:05:00.000Z"
},
"warnings": [
"blocks[0].styles.color is not a supported field and was ignored. Button label color comes from the block-level `buttonTextColor` field. Supported styles fields: backgroundColor, backgroundOpacity, bleed, borderColor, borderRadius, borderWidth, paddingBottom, paddingLeft, paddingRight, paddingTop, textAlign, textColor."
]
}
{
"success": false,
"error": "Provide blockId to mutate a block or content to replace the body."
}
{
"success": false,
"error": "Missing API key. Provide via x-api-key header or Authorization: Bearer <key>"
}
{ "success": false, "error": "No company selected" }
{ "success": false, "error": "Block not found" }
{ "success": false, "error": "Internal server error" }
Update Email Blocks
You can replace an email body with raw HTML or structured blocks. You can also mutate an existing block betweentext and html.
Request
string
required
Email ID.
string
Raw HTML body. Replaces all blocks with a native HTML body.
array
Structured email blocks. Replaces all existing blocks. Put block styling under
styles; top-level style keys like backgroundColor, backgroundOpacity,
borderColor, borderWidth, and borderRadius are normalized into styles.Fields that are not part of a block’s schema are discarded rather than
rejected, so the request still succeeds. When that happens the response
includes a
warnings array naming each ignored field and listing the fields
that block does accept. Check warnings before treating a 200 as “every field
I sent took effect”. See Block styling vs block
fields.string
Existing block ID to mutate.
string
New block type. Type mutation supports
text and html.string
Optional replacement content for the mutated block.
curl -X PATCH "https://api.sequenzy.com/api/v1/emails/email_123/blocks" \
-H "Authorization: Bearer API_KEY" \
-H "Content-Type: application/json" \
-d '{"blockId":"legacy-block","type":"html"}'
Block styling vs block fields
styles holds the layout and background of the block’s own container - the band
the block sits in. Some blocks render an inner element whose appearance is
controlled by dedicated top-level fields instead. Setting the styles key
changes the band, not the inner element.
The button block is the common case:
| What you want to change | Field to set | What styles does instead |
|---|---|---|
| Button fill color | buttonColor | styles.backgroundColor colors the band behind it |
| Button label color | buttonTextColor | styles.textColor does not reach the label |
buttonColor and buttonTextColor unset to inherit the email theme’s
primary color.
curl -X PATCH "https://api.sequenzy.com/api/v1/emails/email_123/blocks" \
-H "Authorization: Bearer API_KEY" \
-H "Content-Type: application/json" \
-d '{
"blocks": [
{
"id": "cta",
"type": "button",
"text": "Buy now",
"url": "https://example.com",
"variant": "primary",
"buttonColor": "#1d4ed8",
"buttonTextColor": "#ffffff"
}
]
}'
Responses
{
"success": true,
"email": {
"id": "email_123",
"companyId": "company_123",
"name": "Welcome",
"subject": "Welcome",
"previewText": null,
"blocks": [{ "id": "legacy-block", "type": "html", "content": "<table>...</table>" }],
"createdAt": "2026-04-19T12:00:00.000Z",
"updatedAt": "2026-04-19T12:05:00.000Z"
}
}
{
"success": true,
"email": {
"id": "email_123",
"companyId": "company_123",
"name": "Welcome",
"subject": "Welcome",
"previewText": null,
"blocks": [
{
"id": "cta",
"type": "button",
"text": "Buy now",
"url": "https://example.com",
"variant": "primary"
}
],
"createdAt": "2026-04-19T12:00:00.000Z",
"updatedAt": "2026-04-19T12:05:00.000Z"
},
"warnings": [
"blocks[0].styles.color is not a supported field and was ignored. Button label color comes from the block-level `buttonTextColor` field. Supported styles fields: backgroundColor, backgroundOpacity, bleed, borderColor, borderRadius, borderWidth, paddingBottom, paddingLeft, paddingRight, paddingTop, textAlign, textColor."
]
}
{
"success": false,
"error": "Provide blockId to mutate a block or content to replace the body."
}
{
"success": false,
"error": "Missing API key. Provide via x-api-key header or Authorization: Bearer <key>"
}
{ "success": false, "error": "No company selected" }
{ "success": false, "error": "Block not found" }
{ "success": false, "error": "Internal server error" }
⌘I
Update Email Blocks
curl --request PATCH \
--url https://api.sequenzy.com/api/v1/emails/{emailId}/blocks \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"html": "<string>",
"blocks": [
{}
],
"blockId": "<string>",
"type": "<string>",
"content": "<string>"
}
'import requests
url = "https://api.sequenzy.com/api/v1/emails/{emailId}/blocks"
payload = {
"html": "<string>",
"blocks": [{}],
"blockId": "<string>",
"type": "<string>",
"content": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
html: '<string>',
blocks: [{}],
blockId: '<string>',
type: '<string>',
content: '<string>'
})
};
fetch('https://api.sequenzy.com/api/v1/emails/{emailId}/blocks', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.sequenzy.com/api/v1/emails/{emailId}/blocks",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'html' => '<string>',
'blocks' => [
[
]
],
'blockId' => '<string>',
'type' => '<string>',
'content' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.sequenzy.com/api/v1/emails/{emailId}/blocks"
payload := strings.NewReader("{\n \"html\": \"<string>\",\n \"blocks\": [\n {}\n ],\n \"blockId\": \"<string>\",\n \"type\": \"<string>\",\n \"content\": \"<string>\"\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.patch("https://api.sequenzy.com/api/v1/emails/{emailId}/blocks")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"html\": \"<string>\",\n \"blocks\": [\n {}\n ],\n \"blockId\": \"<string>\",\n \"type\": \"<string>\",\n \"content\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sequenzy.com/api/v1/emails/{emailId}/blocks")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"html\": \"<string>\",\n \"blocks\": [\n {}\n ],\n \"blockId\": \"<string>\",\n \"type\": \"<string>\",\n \"content\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"email": {
"id": "email_123",
"companyId": "company_123",
"name": "Welcome",
"subject": "Welcome",
"previewText": null,
"blocks": [{ "id": "legacy-block", "type": "html", "content": "<table>...</table>" }],
"createdAt": "2026-04-19T12:00:00.000Z",
"updatedAt": "2026-04-19T12:05:00.000Z"
}
}
{
"success": true,
"email": {
"id": "email_123",
"companyId": "company_123",
"name": "Welcome",
"subject": "Welcome",
"previewText": null,
"blocks": [
{
"id": "cta",
"type": "button",
"text": "Buy now",
"url": "https://example.com",
"variant": "primary"
}
],
"createdAt": "2026-04-19T12:00:00.000Z",
"updatedAt": "2026-04-19T12:05:00.000Z"
},
"warnings": [
"blocks[0].styles.color is not a supported field and was ignored. Button label color comes from the block-level `buttonTextColor` field. Supported styles fields: backgroundColor, backgroundOpacity, bleed, borderColor, borderRadius, borderWidth, paddingBottom, paddingLeft, paddingRight, paddingTop, textAlign, textColor."
]
}
{
"success": false,
"error": "Provide blockId to mutate a block or content to replace the body."
}
{
"success": false,
"error": "Missing API key. Provide via x-api-key header or Authorization: Bearer <key>"
}
{ "success": false, "error": "No company selected" }
{ "success": false, "error": "Block not found" }
{ "success": false, "error": "Internal server error" }