The Temway Public API provides programmatic access to your workspace's emails, layouts, and branding.
It supports both read (retrieve published content) and write operations
(create, update, delete, duplicate), plus asynchronous rendering, publishing,
and test sending. It is the same surface the Temway MCP server drives, and is designed for
integrations with CMS platforms, automation tools, and custom applications.
Authentication is via API keys, which are scoped to a specific workspace and carry
resource scopes that gate each endpoint. Keys are created and managed from the API Keys
entry in the Temway app's main sidebar.
Base URL
https://api.temway.com/api/v1/public
All Public API endpoints are prefixed with /api/v1/public. The paths below omit this prefix for brevity.
Authentication
Every request must include an API key in the Authorization header using the Bearer scheme:
The Retry-After header (seconds) is only present when the per-minute limit has been exceeded and
the response status is 429. Test sends are additionally subject to a per-user rolling 24-hour
cap derived from your plan (see Test Send Email) — that quota returns a
separate error body.
Errors
The Public API returns consistent error responses with the following structure:
API key expired, missing the required scope, or not authorized for this workspace
403
PLAN_LIMIT
A plan limit or feature gate was exceeded (e.g. email count, monthly exports). Body includes suggestedPlan.
404
NOT_FOUND
Requested resource does not exist or is not in the expected state
409
CONFLICT
State conflict — e.g. a render job is not completed, the wrong render target was supplied, or no email-target HTML is available (see Get Published Email HTML)
422
VALIDATION_ERROR
Malformed request body or invalid email/layout content (rejected by the schema validator)
429
TOO_MANY_REQUESTS
Per-minute rate limit exceeded. Check the Retry-After header.
429
RATE_LIMIT_EXCEEDED
Test-send daily quota exceeded. Body carries limit, used, windowHours, plan, and optional suggestedPlan.
Pagination
List endpoints return paginated results with the following shape:
Use the page and limit query parameters to navigate. Default limit is 20, maximum is 100.
Async Jobs (Export, Publish, Send)
Three email operations are asynchronous and follow a deliberate two-step pattern — you trigger
a job, then poll it to completion by its explicit ID:
Export (POST /:id/export) enqueues a render job and returns { jobId, status } with HTTP 202. Each export renders exactly one target — email (MJML/table HTML) or web (semantic HTML5) — set by the target query param.
Publish (POST /:id/publish) consumes a completedtarget='web' render job (pass its renderJobId): copies the web HTML into the email, sets status='published', and snapshots a version.
Test send (POST /:id/test-send) consumes a completedtarget='email' render job (pass its renderJobId) and enqueues a send to the to address.
Poll render jobs via GET /:id/render-jobs/:jobId (or /latest) and send jobs via
GET /:id/send-jobs/:jobId (or /latest). Always reference a render job by its
explicit ID — never assume "latest completed", since a newer web-only publish job can shadow an email
render.
Emails
All email endpoints are mounted under /workspaces/:workspaceId/emails.
List Published Emails
GET /workspaces/:workspaceId/emails API Key
Retrieve a paginated list of published emails in a workspace. Only emails with status <code>published</code> are returned. Supports optional search by name or subject.
Path Parameters
Name
Type
Description
workspaceId
string
Workspace ID
Query Parameters
Name
Type
Description
Required
page
integer
Page number (default: 1)
No
limit
integer
Items per page (default: 20, max: 100)
No
search
string
Search query — matches against email name or subject
No
Response
{
"data": [
{
"id": "email_abc123",
"name": "Welcome Email",
"subject": "Welcome to Temway!",
"preheaderText": "Get started with your account",
"tags": ["onboarding"],
"status": "published",
"updatedAt": "2026-06-26T12:00:00.000Z"
}
],
"total": 1,
"page": 1,
"limit": 20
}
Status Codes
Code
Description
200
List of published emails
401
Missing or invalid API key
403
API key lacks emails:read scope or is not authorized for this workspace
429
Rate limit exceeded
Get Published Email
GET /workspaces/:workspaceId/emails/:id API Key
Retrieve a single published email's metadata by its ID. Returns 404 if the email does not exist or is not in <code>published</code> status.
Path Parameters
Name
Type
Description
workspaceId
string
Workspace ID
id
string
Email ID
Response
{
"id": "email_abc123",
"name": "Welcome Email",
"subject": "Welcome to Temway!",
"preheaderText": "Get started with your account",
"tags": ["onboarding"],
"status": "published",
"updatedAt": "2026-06-26T12:00:00.000Z"
}
Status Codes
Code
Description
200
Published email metadata
401
Missing or invalid API key
403
API key lacks emails:read scope or is not authorized for this workspace
404
Email not found or not published
429
Rate limit exceeded
Get Published Email HTML
GET /workspaces/:workspaceId/emails/:id/html API Key
Retrieve the <strong>email-target</strong> HTML (<code>emails.html</code> — MJML-rendered, table-based) of a published email, along with its plain-text alternative. Returns 404 if the email is not found or not published. Returns 409 if no email-target HTML is available — this happens when the email has never been rendered as an email target, or after a <code>target='web'</code> publish (which populates web HTML but nulls the email-target HTML). Run <code>POST /:id/export?target=email</code> to populate it.
Path Parameters
Name
Type
Description
workspaceId
string
Workspace ID
id
string
Email ID
Response
{
"html": "<!DOCTYPE html>\n<html>...",
"text": "Plain text version of the email...",
"subject": "Welcome to Temway!",
"preheaderText": "Get started with your account",
"updatedAt": "2026-06-26T12:00:00.000Z"
}
Status Codes
Code
Description
200
Email-target HTML returned
401
Missing or invalid API key
403
API key lacks emails:read scope or is not authorized for this workspace
404
Email not found or not published
409
No email-target HTML available — export with ?target=email first
429
Rate limit exceeded
Get Draft Email (for editing)
GET /workspaces/:workspaceId/emails/:id/edit API Key
Retrieve the full email row in <strong>any</strong> status (including <code>draft</code>), including its <code>content</code> object. This is the endpoint authoring clients use to fetch what they are editing. Distinct path keeps the published-only contract of <code>GET /:id</code> untouched.
Path Parameters
Name
Type
Description
workspaceId
string
Workspace ID
id
string
Email ID
Status Codes
Code
Description
200
Full email row (any status, includes content)
401
Missing or invalid API key
403
API key lacks emails:read scope or is not authorized for this workspace
404
Email not found in this workspace
429
Rate limit exceeded
Create Email
POST /workspaces/:workspaceId/emails API Key
Create a new draft email in the workspace. <code>content</code> is the email-builder block tree (validated leniently; malformed content is normalized and logged, never rejected with a hard error). Subject to the plan's email-count limit (returns 403 <code>PLAN_LIMIT</code> when exceeded).
Missing emails:write scope, not authorized, or PLAN_LIMIT (email count reached)
422
Malformed request body
429
Rate limit exceeded
Update Email
PATCH /workspaces/:workspaceId/emails/:id API Key
Update an existing email. All fields are optional; pass only what you want to change. Updating <code>content</code> does not automatically re-publish — call the publish flow to refresh the stored HTML.
DELETE /workspaces/:workspaceId/emails/:id API Key
Soft-delete an email. The row is retained (it no longer counts toward plan limits) and is excluded from list results. Returns an empty body.
Path Parameters
Name
Type
Description
workspaceId
string
Workspace ID
id
string
Email ID
Status Codes
Code
Description
204
Email deleted (empty body)
401
Missing or invalid API key
403
Missing emails:write scope or not authorized
404
Email not found in this workspace
429
Rate limit exceeded
Duplicate Email
POST /workspaces/:workspaceId/emails/:id/duplicate API Key
Create a draft copy of an email. The copy resets to <code>status='draft'</code> with no rendered HTML. Subject to the plan's email-count limit.
Path Parameters
Name
Type
Description
workspaceId
string
Workspace ID
id
string
Email ID to duplicate
Request Body
{
"name": "Copy of Welcome Email" // optional — defaults to "Copy of <original>"
}
Status Codes
Code
Description
201
Duplicated email created (status: draft)
401
Missing or invalid API key
403
Missing emails:write scope, not authorized, or PLAN_LIMIT
404
Source email not found in this workspace
422
Malformed request body
429
Rate limit exceeded
Create Email from Layout
POST /workspaces/:workspaceId/emails/from-layout API Key
Create a new draft email seeded from a published layout's content. The email's <code>layoutId</code> is linked to the source layout. Subject to the plan's email-count limit.
Missing emails:write scope, not authorized, or PLAN_LIMIT
404
Layout not found in this workspace
422
Malformed request body
429
Rate limit exceeded
Export (Render) Email
POST /workspaces/:workspaceId/emails/:id/export API Key
Enqueue an asynchronous render job. Each job renders exactly <strong>one</strong> target: <code>email</code> (MJML/table HTML, for inboxes) or <code>web</code> (semantic HTML5, for share/template embeds). Returns the job ID with HTTP 202 — poll <code>GET /:id/render-jobs/:jobId</code> until <code>status='completed'</code>, then read <code>outputHtml</code> (email target) or <code>outputHtmlWeb</code> (web target). Subject to the plan's monthly export limit.
Missing emails:write scope, not authorized, or PLAN_LIMIT (monthly exports)
404
Email not found in this workspace
429
Rate limit exceeded
Get Render Job
GET /workspaces/:workspaceId/emails/:id/render-jobs/:jobId API Key
Poll a render job by its explicit ID. <code>outputHtml</code> is populated only for email-target jobs; <code>outputHtmlWeb</code> only for web-target jobs. Use <code>/render-jobs/latest</code> for the most recent job (registered before the parametric route).
Path Parameters
Name
Type
Description
workspaceId
string
Workspace ID
id
string
Email ID
jobId
string
Render job ID (or 'latest')
Response
{
"id": "rjob_xyz789",
"status": "completed", // pending | processing | completed | failed
"target": "email",
"outputHtml": "<!DOCTYPE html>...", // email target only (null for web)
"outputHtmlWeb": null, // web target only (null for email)
"errorMessage": null,
"createdAt": "2026-07-02T10:00:00.000Z",
"completedAt": "2026-07-02T10:00:08.000Z"
}
Status Codes
Code
Description
200
Render job details
401
Missing or invalid API key
403
Missing emails:read scope or not authorized
404
Email or render job not found
429
Rate limit exceeded
Publish Email
POST /workspaces/:workspaceId/emails/:id/publish API Key
Publish an email by consuming a <strong>completed web-target render job</strong>. Copies the web HTML into the email, sets <code>status='published'</code>, and snapshots a version (enforcing the plan's version cap). The render job must belong to this email and have <code>outputHtmlWeb</code> (a 409 is returned for an email-target render or an incomplete job).
Path Parameters
Name
Type
Description
workspaceId
string
Workspace ID
id
string
Email ID
Request Body
{
"renderJobId": "rjob_xyz789" // required — must be a completed target='web' render
}
Status Codes
Code
Description
200
Email published (status: published)
401
Missing or invalid API key
403
Missing emails:write scope or not authorized
404
Email or render job not found
409
Render job not completed, or has no web output (use target=web)
422
Malformed request body
429
Rate limit exceeded
Test Send Email
POST /workspaces/:workspaceId/emails/:id/test-send API Key
Send a test email to <code>to</code> by consuming a <strong>completed email-target render job</strong>. The render job must have <code>outputHtml</code> (a 409 is returned for a web-target render). Subject to a <strong>per-user rolling 24-hour cap</strong> derived from the plan (Free 5, Starter 20, Pro 50, Max 100). When the daily cap is hit, the response is 429 with <code>code='RATE_LIMIT_EXCEEDED'</code> and a body carrying <code>limit</code>, <code>used</code>, <code>windowHours</code>, <code>plan</code>, and optional <code>suggestedPlan</code>.
Path Parameters
Name
Type
Description
workspaceId
string
Workspace ID
id
string
Email ID
Request Body
{
"to": "[email protected]", // required — recipient email
"renderJobId": "rjob_xyz789" // required — must be a completed target='email' render
}
Response
{
"jobId": "sjob_qrs456",
"status": "pending"
}
Status Codes
Code
Description
202
Send job enqueued
401
Missing or invalid API key
403
Missing emails:write scope or not authorized
404
Email or render job not found
409
Render job not completed, or has no email output (use target=email)
422
Malformed request body
429
Per-minute rate limit OR daily test-send quota exceeded
Get Send Job
GET /workspaces/:workspaceId/emails/:id/send-jobs/:jobId API Key
Poll a send job by its explicit ID. <code>providerMessageId</code> is set on a successful delivery (for later webhook reconciliation). Use <code>/send-jobs/latest</code> for the most recent job.
All layout endpoints are mounted under /workspaces/:workspaceId/layouts. Layouts have no async render/export/send flow — publishing is synchronous.
List Published Layouts
GET /workspaces/:workspaceId/layouts API Key
Retrieve a paginated list of published layouts in a workspace. Only layouts with status <code>published</code> are returned. Supports optional search and category filters.
Path Parameters
Name
Type
Description
workspaceId
string
Workspace ID
Query Parameters
Name
Type
Description
Required
page
integer
Page number (default: 1)
No
limit
integer
Items per page (default: 20, max: 100)
No
search
string
Search query — matches against layout name or description
API key lacks layouts:read scope or is not authorized for this workspace
404
Layout not found or not published
429
Rate limit exceeded
Get Draft Layout (for editing)
GET /workspaces/:workspaceId/layouts/:id/edit API Key
Retrieve the full layout row in <strong>any</strong> status (including <code>draft</code>), including its <code>content</code> object. This is the endpoint authoring clients use to fetch what they are editing.
Path Parameters
Name
Type
Description
workspaceId
string
Workspace ID
id
string
Layout ID
Status Codes
Code
Description
200
Full layout row (any status, includes content)
401
Missing or invalid API key
403
API key lacks layouts:read scope or is not authorized for this workspace
404
Layout not found in this workspace
429
Rate limit exceeded
Create Layout
POST /workspaces/:workspaceId/layouts API Key
Create a new draft layout. <code>content</code> is the layout-editor descriptor. <code>canvas</code> constrains dimensions (width 200–1200, height 200–3000). Subject to the plan's layout-count limit.
Missing layouts:write scope, not authorized, or PLAN_LIMIT (layout count)
422
Malformed request body
429
Rate limit exceeded
Update Layout
PATCH /workspaces/:workspaceId/layouts/:id API Key
Update an existing layout. All fields are optional; pass only what you want to change. Updating <code>content</code> does not automatically re-publish.
DELETE /workspaces/:workspaceId/layouts/:id API Key
Soft-delete a layout. Returns an empty body.
Path Parameters
Name
Type
Description
workspaceId
string
Workspace ID
id
string
Layout ID
Status Codes
Code
Description
204
Layout deleted (empty body)
401
Missing or invalid API key
403
Missing layouts:write scope or not authorized
404
Layout not found in this workspace
429
Rate limit exceeded
Duplicate Layout
POST /workspaces/:workspaceId/layouts/:id/duplicate API Key
Create a draft copy of a layout. Subject to the plan's layout-count limit.
Path Parameters
Name
Type
Description
workspaceId
string
Workspace ID
id
string
Layout ID to duplicate
Request Body
{
"name": "Copy of Newsletter Template" // optional — defaults to "Copy of <original>"
}
Status Codes
Code
Description
201
Duplicated layout created (status: draft)
401
Missing or invalid API key
403
Missing layouts:write scope, not authorized, or PLAN_LIMIT
404
Source layout not found in this workspace
422
Malformed request body
429
Rate limit exceeded
Publish Layout
POST /workspaces/:workspaceId/layouts/:id/publish API Key
Publish a layout synchronously — sets <code>status='published'</code> against the layout's current content. Unlike emails, layouts have no async render step (they are SVG art, not MJML), so publishing takes no request body and no render job.
Path Parameters
Name
Type
Description
workspaceId
string
Workspace ID
id
string
Layout ID
Status Codes
Code
Description
200
Layout published (status: published)
401
Missing or invalid API key
403
Missing layouts:write scope or not authorized
404
Layout not found in this workspace
429
Rate limit exceeded
Branding
Get Workspace Branding
GET /workspaces/:workspaceId/branding API Key
Retrieve the workspace's branding configuration (colors, fonts, logo, sender defaults). Used to render emails with brand-consistent metadata. Requires <code>emails:read</code> <em>or</em> <code>layouts:read</code>.
Missing read scope or not authorized for this workspace
429
Rate limit exceeded
API Key
Get Current Key
GET /me API Key
Resolve the authenticated API key itself. Returns the workspace, team, and scopes the key carries. Not workspace-scoped (mounted without <code>:workspaceId</code>), so it has no scope gate — any valid key resolves itself. The remote MCP server uses this to derive the workspace from a bare key on session init.
API keys are created from the API Keys entry in the Temway app's main sidebar. Once you have a key, you can
read published content, author new emails, render, publish, and test-send.