Send up to 100 messages, each with its own recipient and data
# REPUTECAST_API_KEY: an API key (rc_live_…) with transactional:send. Up to 100 messages per call.# Replace reputecast.example.com with your public URL and your-workspace with your workspace slug.curl --request POST \ --url https://reputecast.example.com/api/v1/workspaces/your-workspace/transactional/messages/batch \ --header "Authorization: Bearer $REPUTECAST_API_KEY" \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: welcome-2026-10-22-0900' \ --data '{ "messages": [ { "template": "welcome", "to": { "email": "[email protected]", "name": "Priya Shah" }, "data": { "first_name": "Priya", "dashboard_url": "https://app.example.com/" } }, { "template": "welcome", "to": { "email": "[email protected]" }, "data": { "dashboard_url": "https://app.example.com/" } } ] }'// REPUTECAST_API_KEY: an API key (rc_live_…) with transactional:send. Up to 100 messages per call.// Replace reputecast.example.com with your public URL and your-workspace with your workspace slug.const response = await fetch( 'https://reputecast.example.com/api/v1/workspaces/your-workspace/transactional/messages/batch', { method: 'POST', headers: { Authorization: `Bearer ${process.env.REPUTECAST_API_KEY}`, 'Content-Type': 'application/json', // A retry of the same batch within 24 hours never sends twice. 'Idempotency-Key': 'welcome-2026-10-22-0900', }, body: JSON.stringify({ messages: [ { template: 'welcome', data: { first_name: 'Priya', dashboard_url: 'https://app.example.com/' }, }, { template: 'welcome', data: { dashboard_url: 'https://app.example.com/' }, }, ], }), },)const result = await response.json()if (!response.ok) throw new Error(`${response.status} ${result.code}: ${result.detail}`)console.log(`${result.accepted} accepted, ${result.failed} failed`)// One result per message, in the order sent: its ID and status, or the problem that stopped it.for (const item of result.results) { console.log(item.index, item.status, item.id ?? `${item.error.code}: ${item.error.detail}`)}// REPUTECAST_API_KEY: an API key (rc_live_…) with transactional:send. Up to 100 messages per call.// Replace reputecast.example.com with your public URL and your-workspace with your workspace slug.package main
import ( "bytes" "encoding/json" "fmt" "log" "net/http" "os")
func main() { body, err := json.Marshal(map[string]any{ "messages": []map[string]any{ { "template": "welcome", "data": map[string]string{"first_name": "Priya", "dashboard_url": "https://app.example.com/"}, }, { "template": "welcome", "data": map[string]string{"dashboard_url": "https://app.example.com/"}, }, }, }) if err != nil { log.Fatal(err) } req, err := http.NewRequest(http.MethodPost, "https://reputecast.example.com/api/v1/workspaces/your-workspace/transactional/messages/batch", bytes.NewReader(body)) if err != nil { log.Fatal(err) } req.Header.Set("Authorization", "Bearer "+os.Getenv("REPUTECAST_API_KEY")) req.Header.Set("Content-Type", "application/json") // A retry of the same batch within 24 hours never sends twice. req.Header.Set("Idempotency-Key", "welcome-2026-10-22-0900")
resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close()
type problem struct { Code string `json:"code"` Detail string `json:"detail"` } var result struct { problem Accepted int `json:"accepted"` Failed int `json:"failed"` Results []struct { Index int `json:"index"` Status string `json:"status"` ID string `json:"id"` Error *problem `json:"error"` } `json:"results"` } if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { log.Fatal(err) } if resp.StatusCode >= 300 { log.Fatalf("%d %s: %s", resp.StatusCode, result.Code, result.Detail) } fmt.Printf("%d accepted, %d failed\n", result.Accepted, result.Failed) // One result per message, in the order sent: its ID and status, or the problem that stopped it. for _, item := range result.Results { if item.Error != nil { fmt.Println(item.Index, item.Status, item.Error.Code+": "+item.Error.Detail) continue } fmt.Println(item.Index, item.Status, item.ID) }}# REPUTECAST_API_KEY: an API key (rc_live_…) with transactional:send. Up to 100 messages per call.# Replace reputecast.example.com with your public URL and your-workspace with your workspace slug.import os
import requests
response = requests.post( "https://reputecast.example.com/api/v1/workspaces/your-workspace/transactional/messages/batch", headers={ "Authorization": f"Bearer {os.environ['REPUTECAST_API_KEY']}", # A retry of the same batch within 24 hours never sends twice. "Idempotency-Key": "welcome-2026-10-22-0900", }, json={ "messages": [ { "template": "welcome", "data": {"first_name": "Priya", "dashboard_url": "https://app.example.com/"}, }, { "template": "welcome", "data": {"dashboard_url": "https://app.example.com/"}, }, ] }, timeout=30,)result = response.json()if not response.ok: raise RuntimeError(f"{response.status_code} {result.get('code')}: {result.get('detail')}")print(f"{result['accepted']} accepted, {result['failed']} failed")# One result per message, in the order sent: its ID and status, or the problem that stopped it.for item in result["results"]: if "error" in item: print(item["index"], item["status"], f"{item['error']['code']}: {item['error']['detail']}") else: print(item["index"], item["status"], item["id"])<?php// REPUTECAST_API_KEY: an API key (rc_live_…) with transactional:send. Up to 100 messages per call.// Replace reputecast.example.com with your public URL and your-workspace with your workspace slug.$payload = [ 'messages' => [ [ 'template' => 'welcome', 'data' => ['first_name' => 'Priya', 'dashboard_url' => 'https://app.example.com/'], ], [ 'template' => 'welcome', 'data' => ['dashboard_url' => 'https://app.example.com/'], ], ],];
$ch = curl_init('https://reputecast.example.com/api/v1/workspaces/your-workspace/transactional/messages/batch');curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . getenv('REPUTECAST_API_KEY'), 'Content-Type: application/json', // A retry of the same batch within 24 hours never sends twice. 'Idempotency-Key: welcome-2026-10-22-0900', ], CURLOPT_POSTFIELDS => json_encode($payload, JSON_THROW_ON_ERROR),]);$body = curl_exec($ch);if ($body === false) { throw new RuntimeException(curl_error($ch));}$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);$result = json_decode($body, true, flags: JSON_THROW_ON_ERROR);if ($status >= 300) { throw new RuntimeException("{$status} {$result['code']}: {$result['detail']}");}echo "{$result['accepted']} accepted, {$result['failed']} failed", PHP_EOL;// One result per message, in the order sent: its ID and status, or the problem that stopped it.foreach ($result['results'] as $item) { $outcome = isset($item['error']) ? "{$item['error']['code']}: {$item['error']['detail']}" : $item['id']; echo "{$item['index']} {$item['status']} {$outcome}", PHP_EOL;}Permission: transactional:send (sensitive)
Each message gets its own answer in results, in the order sent: its ID and status, or the problem that stopped it (the same codes as one send).
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”Workspace slug
Workspace slug
Header Parameters
Section titled “Header Parameters”A retry of the same batch within 24 hours never sends twice
A retry of the same batch within 24 hours never sends twice
Request Bodyrequired
Section titled “Request Bodyrequired”object
object
object
The file, base64-encoded
Makes it an inline image the HTML references as cid:<content_id>
Guessed from the file name when omitted
object
object
The template’s variables
object
A verified Transactional sender, as an address or “Name
”; the template’s sender when omittedThe language version to send; the linked contact’s language, then the fallback, when omitted
object
Overrides the template’s preheader (Liquid)
Send later, up to 72 hours ahead
Overrides the template’s subject (Liquid)
Returned with every webhook event of the message
The template’s ID
object
Responses
Section titled “Responses”OK
object
object
object
Stable error code, e.g. permission_denied
A human-readable explanation specific to this occurrence of the problem.
Optional list of individual error details
object
Where the error occurred, e.g. ‘body.items[3].tags’ or ‘path.thing-id’
Error message text
The value at the given location
Members who hold the missing permission
A URI reference that identifies the specific occurrence of the problem.
object
Required variables the call didn’t send (missing_variables)
The missing permission key
HTTP status code
A short, human-readable summary of the problem type. This value should not change between occurrences of the error.
A URI reference to human-readable documentation for the error.
Example
{ "results": [ { "error": { "detail": "Property foo is required but is missing.", "instance": "https://example.com/error-log/abc123", "status": 400, "title": "Bad Request", "type": "about:blank" }, "status": "queued" } ]}default
Section titled “default”Error
object
Stable error code, e.g. permission_denied
A human-readable explanation specific to this occurrence of the problem.
Optional list of individual error details
object
Where the error occurred, e.g. ‘body.items[3].tags’ or ‘path.thing-id’
Error message text
The value at the given location
Members who hold the missing permission
A URI reference that identifies the specific occurrence of the problem.
object
The missing permission key
HTTP status code
A short, human-readable summary of the problem type. This value should not change between occurrences of the error.
A URI reference to human-readable documentation for the error.
Example
{ "detail": "Property foo is required but is missing.", "instance": "https://example.com/error-log/abc123", "status": 400, "title": "Bad Request", "type": "about:blank"}