Base URL: https://mailforge.grabshot.dev
All API endpoints require an API key passed via the x-api-key header. Get your free key from the dashboard.
Include your API key in the x-api-key header with every request:
curl -H "x-api-key: mf_your_key_here" https://mailforge.grabshot.dev/v1/render
Render an HTML template with JSON data using Handlebars syntax. Supports variables, loops, conditionals, and helpers.
| Field | Type | Description |
|---|---|---|
template | string | HTML template with Handlebars syntax required |
html | string | Alias for template optional |
data | object | JSON data to inject into template optional |
format | string | html (default) or inlined (also inline CSS) optional |
curl -X POST https://mailforge.grabshot.dev/v1/render \
-H "x-api-key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"template": "<h1>Hello {{name}}</h1><p>Welcome to {{company}}</p>",
"data": {"name": "John", "company": "Acme Inc"}
}'
const resp = await fetch('https://mailforge.grabshot.dev/v1/render', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': 'YOUR_KEY'
},
body: JSON.stringify({
template: '<h1>Hello {{name}}</h1>',
data: { name: 'John' }
})
});
const { html } = await resp.json();
import requests
resp = requests.post(
'https://mailforge.grabshot.dev/v1/render',
headers={'x-api-key': 'YOUR_KEY'},
json={
'template': '<h1>Hello {{name}}</h1>',
'data': {'name': 'John'}
}
)
html = resp.json()['html']
{
"success": true,
"html": "<h1>Hello John</h1><p>Welcome to Acme Inc</p>",
"original_size": 52,
"rendered_size": 48,
"data_keys": 2
}
Convert CSS <style> blocks to inline styles. Critical for email client compatibility - most email clients strip <style> tags.
| Field | Type | Description |
|---|---|---|
html | string | HTML with CSS to inline required |
curl -X POST https://mailforge.grabshot.dev/v1/inline \
-H "x-api-key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"html": "<style>h1{color:red;font-size:24px}</style><h1>Hello</h1>"}'
{
"success": true,
"html": "<h1 style=\"color: red; font-size: 24px;\">Hello</h1>",
"original_size": 54,
"inlined_size": 52
}
Render HTML email as a pixel-perfect screenshot. Useful for previewing how emails will look at different viewport widths.
| Field | Type | Description |
|---|---|---|
html | string | HTML to render required* |
template | string | Handlebars template (with data) optional |
data | object | Template data optional |
width | number | Viewport width in px (default: 600) optional |
height | number | Viewport height in px (default: 800) optional |
format | string | png (default) or jpeg optional |
quality | number | JPEG quality 1-100 (default: 80) optional |
curl -X POST https://mailforge.grabshot.dev/v1/preview \
-H "x-api-key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"html": "<h1 style=\"color:orange\">Hello!</h1>", "width": 600}' \
--output preview.png
Returns the screenshot as a binary image (PNG or JPEG) with appropriate Content-Type header.
Check HTML email for common compatibility issues, spam triggers, and best practices.
| Field | Type | Description |
|---|---|---|
html | string | HTML email to validate required |
curl -X POST https://mailforge.grabshot.dev/v1/validate \
-H "x-api-key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"html": "<html><body><img src=\"logo.png\"><script>alert(1)</script></body></html>"}'
{
"success": true,
"score": 40,
"issues": [
{"type": "error", "code": "MISSING_ALT", "message": "1 image(s) missing alt attribute"},
{"type": "error", "code": "JAVASCRIPT", "message": "JavaScript found. Email clients strip all JavaScript."}
],
"warnings": [
{"type": "warning", "code": "NO_DARK_MODE", "message": "No dark mode support detected."}
],
"passes": [
{"code": "INLINE_STYLES", "message": "No <style> blocks (good)"},
{"code": "HTML_SIZE", "message": "HTML size is 0KB (under 102KB limit)"}
],
"summary": {"errors": 2, "warnings": 1, "passes": 2, "images": 1, "size_kb": 0}
}
Health check. No auth required.
Create a new account. Body: {"email": "[email protected]"}
Validate an API key. Body: {"key": "mf_..."}
Get current usage stats and plan info.
List available plans and pricing.
Create a Stripe checkout session for plan upgrade. Body: {"plan": "pro"}
| Plan | Requests/min | Requests/month |
|---|---|---|
| Free | 5 | 100 |
| Starter | 20 | 500 |
| Pro | 60 | 5,000 |
| Business | 120 | 50,000 |
All errors return JSON with success: false:
{
"success": false,
"error": "API key required. Pass via x-api-key header."
}
| Status | Meaning |
|---|---|
| 400 | Bad request (missing/invalid parameters) |
| 401 | Unauthorized (missing or invalid API key) |
| 429 | Rate limit or monthly limit exceeded |
| 500 | Server error |