Submit an email template version
/v1/email/templates/{template_ref}/versions/{version_id}/submitconst templateId = "TEMPLATE_ID";
const draftVersionId = "DRAFT_VERSION_ID";
const check = await bird.email.templates.versions.submit(templateId, draftVersionId, {
validate_only: true,
});
for (const problem of check.errors) {
console.log(problem.language, problem.field, problem.message);
}
if (check.valid) {
const result = await bird.email.templates.versions.submit(templateId, draftVersionId);
console.log(result.version?.version_number);
}template_id = "TEMPLATE_ID"
draft_version_id = "DRAFT_VERSION_ID"
check = client.email.templates.versions.submit(template_id, draft_version_id, validate_only=True)
for problem in check.errors:
print(problem.language, problem.field, problem.message)
if check.valid:
result = client.email.templates.versions.submit(template_id, draft_version_id)
if result.version is not None:
print(result.version.version_number)ctx := context.Background()
templateID := "TEMPLATE_ID"
draftVersionID := "DRAFT_VERSION_ID"
check, err := client.Email.Templates.Versions.Submit(ctx, templateID, draftVersionID,
bird.EmailTemplatesVersionsSubmitParams{ValidateOnly: bird.Bool(true)})
if err != nil {
log.Fatal(err)
}
if check.Errors != nil {
for _, problem := range *check.Errors {
fmt.Println(*problem.Message)
}
}
if check.Valid != nil && *check.Valid {
result, err := client.Email.Templates.Versions.Submit(ctx, templateID, draftVersionID,
bird.EmailTemplatesVersionsSubmitParams{})
if err != nil {
log.Fatal(err)
}
fmt.Println(*result.Version.VersionNumber)
}$templateId = 'TEMPLATE_ID';
$draftVersionId = 'DRAFT_VERSION_ID';
$check = $bird->email->templates->versions->submit(
$templateId,
$draftVersionId,
(new EmailTemplateSubmit())->setValidateOnly(true),
);
foreach ($check->getErrors() ?? [] as $problem) {
echo $problem->getLanguage(), ' ', $problem->getField(), ' ', $problem->getMessage(), "\n";
}
if ($check->getValid() === true) {
$result = $bird->email->templates->versions->submit($templateId, $draftVersionId, new EmailTemplateSubmit());
echo $result->getVersion()?->getVersionNumber();
}bird email templates versions submit <template-ref> <version-id> \
--validate-only=truecurl -X POST "https://us1.platform.bird.com/v1/email/templates/{template_ref}/versions/{version_id}/submit" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"validate_only": true
}'{
"errors": [
{
"language": "pt-BR",
"field": "subject",
"code": "E04051",
"message": "A subject is required to submit."
}
],
"version": {
"id": "emv_01krdgeqcxet5s7t44vh8rt9mg",
"template_id": "emt_01krdgeqcxet5s7t44vh8rt9mg",
"status": "published",
"variables": [
{
"type": "code"
}
],
"default_language": "pt-BR",
"updated_by": {
"id": "usr_01krdgeqcxet5s7t44vh8rt9mg",
"type": "user"
}
},
"template_ref": "emt_01krdgeqcxet5s7t44vh8rt9mg",
"version_id": "emv_01krdgeqcxet5s7t44vh8rt9mg",
"compatibility_severity": "warning",
"compatibility": [
{
"rule_id": "css_display_flex_grid",
"severity": "warning",
"language": "pt-BR",
"field": "html",
"message": "`display: flex` and `grid` don't work in Outlook (Windows/Windows Mail).",
"fix": "Use tables for layout.",
"partial": "Partial support for `display: flex` and `grid` in Gmail (iOS/Android).",
"line": 14,
"column": 6,
"match": "display: flex",
"unsupported_clients": [
{
"family": "outlook",
"platforms": [
"windows",
"windows_mail"
]
}
],
"partial_clients": [
{
"family": "outlook",
"platforms": [
"windows",
"windows_mail"
]
}
]
}
]
}
Submits the template's draft as a new immutable, numbered version and makes it the live version used by sends. The draft remains editable.
Every language the draft has must have a subject and a body, and the default language must be present. Submission is all or nothing: an incomplete language rejects the request and the response reports every language error. A submit freezes every language the draft carries, so it cannot name a subset. The draft does not have to hold every language you plan to support: add more in a later version.
Set validate_only: true to run the checks without creating a version.
Set expected_revision to reject a concurrent edit. An unchanged draft is
rejected. Submission is synchronous, and a returned version is live.
参数
template_refstringThe template's id (emt_…) or slug. Submit freezes a draft, and a built-in system template has no draft, so its bird_ slug returns 404 not_found_error here.
version_idstringThe draft version to validate or publish.
请求载荷
validate_onlyCheck the draft without actually submitting it. Every language gets checked and every problem gets reported back to you, but nothing is frozen and no new version gets created. Give a validation run its own Idempotency-Key, separate from the real submit that follows it. You can also send no key. The validation request and real submit have different bodies, so using the same key for both is rejected as key reuse.
expected_revisionThe draft revision you last read (from the template's revision field). A stale value returns a conflict so you can reload and retry.
languagesLanguages to process when submitting an already-published version. Email templates accept submissions only for drafts, so setting this field for an email template is rejected.
响应载荷
validWhether the version passed every check.
errorsEvery problem found across the draft's languages. Empty when valid is true.
versionThe version this submit created, or null when it was only a validation run and nothing got frozen. As soon as this is not null, sends already use that version. No further action is required to make it live.
template_refThe template this submit addressed.
version_idThe draft this submit addressed: the one it froze, or on a validation run the one it checked and left as it was. The frozen version, when there is one, is version.
compatibility_severityThe worst severity across every finding the response was computed from, which
is the authoritative reading: a response that caps how many findings it lists
still accounts here for the ones it left out. Each response's compatibility
says which content it covered.
problem: at least one finding is aproblem.warning: every finding is awarning.none: there are no findings.
Possible values: problem, warning, none
compatibilityWhat the draft's HTML uses that mail clients remove, ignore, or render inconsistently, across every language, in alphabetical order of language tag and then the order the patterns appear. Empty when nothing is worth reporting. Advisory, and separate from errors: a finding never fails a submit, so the version froze either way. Each finding names the language it is in, and its line and column count in that language's HTML, which the language read returns as content.html. At most 200 findings come back, the first 200 in that order, so a draft that reaches the cap can omit a later language's findings entirely rather than trimming each language: read a language's own findings from its read or its write. compatibility_severity is derived from every finding the draft produced, including any beyond those 200.
显示子属性
compatibility.rule_idThe rule that produced this finding.
Possible values (may grow over time): html_script, html_event_handlers, html_embedded_content, html_linked_stylesheet, css_at_import, html_form, html_svg, html_media, css_display_flex_grid, css_position_fixed_sticky, css_variables_no_fallback, css_viewport_units, html_button, css_math_functions, css_modern_color, html_web_page_markup
compatibility.severityWhat a finding costs you.
problem: the pattern does nothing at all. The client removes the markup, never loads the stylesheet carrying it, or will not operate the control. Where a finding names clients, that is what happens in those clients.warning: it does something, but not what you wrote.
Neither one refuses a save, a submit, or a send.
Possible values: problem, warning
compatibility.languageWhich language's content this finding is in. Null when the call covered a single language.
compatibility.fieldWhich field of that language the finding is in. Always html; the subject and the plain-text body are not checked.
compatibility.messageWhat is wrong and which clients it affects, worded to show to whoever is authoring the template. It covers the rule's whole category rather than the exact text that matched, so a rule covering <video> and <audio> names both whichever one is on the line. Show fix and then partial after it.
compatibility.fixWhat to use instead. Null when there is no drop-in alternative and the fix is a restructure.
compatibility.partialWhich clients support the feature only partly. Null when no client's support is partial.
compatibility.lineThe 1-based line the pattern is on, in the HTML the containing response's compatibility says it covered.
compatibility.columnThe 1-based column the pattern starts at, on that line.
compatibility.matchThe source text that matched, starting at line and column: the smallest span that identifies what is wrong. Never the enclosing line. For a finding on a whole element, the span runs from the opening tag through the close tag, because the client drops the element's content along with its markup. Cut at 256 characters, so an element holding a long body is quoted from its start rather than in full.
compatibility.unsupported_clientsEvery client family that does not support the feature at all, in alphabetical order by each entry's family. Empty on a finding whose message, fix, and partial name no client. message names at most four families; this names all of them.
compatibility.partial_clientsEvery client family that renders something other than what you wrote, in alphabetical order by each entry's family. Empty when no client's support is partial, which is also when partial is null. partial names at most four families; this names all of them.
显示子属性
compatibility.partial_clients.familyWhich mail client a finding applies to. A finding's message names at most
Apple Mail, Gmail, Outlook, and Yahoo; its unsupported_clients and
partial_clients name every client affected.
gmail: Gmailoutlook: Outlookyahoo: Yahooapple_mail: Apple Mailaol: AOLthunderbird: Mozilla Thunderbirdsamsung_email: Samsung Emailsfr: SFRorange: Orangeprotonmail: ProtonMailhey: HEYmail_ru: Mail.rufastmail: Fastmaillaposte: LaPoste.netgmx: GMXweb_de: WEB.DEionos_1and1: 1&1wp_pl: WP.pl
Possible values (may grow over time): gmail, outlook, yahoo, apple_mail, aol, thunderbird, samsung_email, sfr, orange, protonmail, hey, mail_ru, fastmail, laposte, gmx, web_de, ionos_1and1, wp_pl
compatibility.partial_clients.platformsWhich of the family's platforms this applies to, in alphabetical order.