Batches
Up to 200 drafts of one kind in one call, written within 8 hours at half the standard rate
A batch sends many drafts of one kind in a single call. S'more writes them on GPU runs shared by every workspace, finishes each item within 8 hours and charges half the writer's standard rate. Each item becomes an ordinary draft that you read, pick from and post or send yourself. S'more posts and sends nothing.
When to use a batch
Use single drafts when a person is waiting for the result. A single draft starts as soon as a GPU is up and takes minutes.
Use a batch when the work can wait a few hours, such as replies to fifty threads for tomorrow or an email for everyone on a list. A batch starts within 2 hours, or right away if a GPU run is already going, and every item is written within 8 hours. Each item costs half as much, and batch items do not count toward the single-draft limits.
A batch takes every kind of draft. All its items share one platform and one type:
platform | type | Item fields | Writer |
|---|---|---|---|
reddit | post | subreddit, plan, confirm_rules_allow_ai | ember-v1, ember-14k, ember-28k |
reddit | reply | subreddit, thread, goal, facts | ember-reply-v1 |
x | post | topic, facts, audience | x-writer-v1 |
x | reply | thread, goal, facts | x-reply-v1 |
email | outreach, follow_up, reply | to, from, goal, facts, thread, length_words | prose-1 |
newsletter, blog | post | topic, facts, audience, outline, title, length_words | prose-1 |
newsletter, blog | rewrite | source_text, instructions, keep_links | prose-1 |
Each item takes the fields of a single draft of that kind, with the same rules, less platform, type, model and idempotency_key, which the batch sets once. An item may also carry count.
How scheduling works
Batch items from every workspace wait in one queue. The Reddit and X writers share one GPU pool and prose-1 has its own, and each pool follows the same rules:
- When you submit, S'more stores the batch with a
deadline_at8 hours later, and its items join the queue. - If a GPU run is already going on the pool, the items ride it and start writing soon after. A run started for single drafts takes batch items while it writes those drafts and for a few minutes after, then stops; items it did not reach keep waiting for a batch run.
- Otherwise S'more holds the items so more work can share one GPU start. A run starts when the oldest waiting item is 2 hours old, or sooner once 200 sends are waiting on the pool. Everything queued rides that run.
- Single drafts go first on every run, so a person waiting on one waits at most for one batch item to finish.
Most items are written long before the deadline. One blog post sent at 10:00 with nothing else queued starts writing at 12:00 and is ready by about 12:10.
The hours after the hold leave room for retries. If no GPU starts, or the day's batch GPU budget is used up, the items keep waiting and S'more tries again until the deadline. Batches have their own GPU budget, so they never use up the time single drafts share. A batch item never fails with gpu_daily_cap, gpu_start_timeout or gpu_refused, and the 6-hour limit that expires a single draft does not apply to it.
An item that is not written by deadline_at ends failed with error.code batch_deadline_missed, and its credits are refunded in full. An item that is already writing at the deadline finishes.
Submit a batch
POST /api/v1/drafts/batches needs the reddit:posts:write scope. This batch asks for replies to three X threads:
curl -s https://app.makesmores.com/api/v1/drafts/batches \
-H "Authorization: Bearer $SMORE_API_KEY" \
-H "Content-Type: application/json" \
-d @- <<JSON | tee batch.json
{
"platform": "x",
"type": "reply",
"idempotency_key": "replies-$(date +%s)",
"items": [
{
"thread": [{ "from": "Original post", "body": "Anyone found a good way to see which subreddits talk about their product?" }],
"goal": "Answer helpfully and mention that mention trackers can do this",
"facts": ["A mention tracker counts a term in one subreddit across its full history"]
},
{
"thread": [{ "from": "Original post", "body": "How do you give an agent access to Reddit data?" }],
"goal": "Answer the question and mention that the S'more API has an MCP server",
"facts": ["Reddit mentions, signals and top posts are available as MCP tools"]
},
{
"thread": [
{ "from": "Original post", "body": "We launched last week and nobody is talking about us yet." },
{ "from": "Reply", "body": "Where are you even looking?" }
],
"goal": "Suggest tracking mentions from before a launch to after it",
"facts": ["Reports show the share of active people who used the term each month"]
}
]
}
JSON
It answers at once:
{
"schema_version": 2,
"batch_id": "8c1f0a52-1d7e-4f43-9a55-0f5b8c9d1e20",
"platform": "x",
"type": "reply",
"model": null,
"state": "queued",
"submitted_at": "2026-10-25T19:00:00Z",
"deadline_at": "2026-10-26T03:00:00Z",
"items": 3,
"price_percent": 50,
"credits_deducted": 1386,
"poll_after_s": 600,
"drafts": [
{ "index": 0, "draft_id": "1b6f3e2a-7c4d-4e8f-9a1b-2c3d4e5f6a70" },
{ "index": 1, "draft_id": "5d2a9c71-0b3e-4f6a-8d1c-7e9f0a2b3c41" },
{ "index": 2, "draft_id": "9e4b1d83-2c5f-4a7b-b0e2-8f1a3c5d7e92" }
]
}
Request fields
| Field | Type | Rules |
|---|---|---|
platform | string | Required. The platform of every item |
type | string | Required. The type of every item |
idempotency_key | string | Required, with the same rules as a draft's key. The same key with the same items returns the stored batch and charges nothing; the same key with different items answers 409 idempotency_conflict |
model | string | Optional. The writer for every item, from the models a single draft of this kind takes. Leave it out for the default |
items | array | Required. 1 to 200 items, each with the fields of a single draft of this kind and an optional count |
Answer fields
| Field | Meaning |
|---|---|
batch_id | The batch's id, for reading it |
platform, type, model | As you sent them. model is null when you left it out |
state | queued until an item starts writing |
submitted_at, deadline_at | When S'more stored the batch, and when every item must be written by: 8 hours later |
items | How many items the batch holds |
price_percent | The share of the standard rate this batch pays. It is stored with the batch, so a later price change never reprices it |
credits_deducted | What the batch took when you submitted: the most every item could cost at the batch rate |
poll_after_s | Seconds to wait before the first read |
drafts | Each item's index, in the order you sent them, with its draft_id |
For these three replies, credits_deducted is each item's 16 candidates at their 384-token limit plus the prompt, at the batch rate: about 1,386 credits (about $1.39 at list) at today's rates. Each item then settles at the tokens it used and the rest is refunded.
Submit over MCP
smore_draft_batch takes the same arguments: platform, type, an optional model, idempotency_key and items. It returns the same answer as structured content.
curl -s https://app.makesmores.com/api/v1/mcp \
-H "Authorization: Bearer $SMORE_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d @- <<JSON | sed -n -e 's/^data: //' -e '/^{/p' | jq '.result.structuredContent | {batch_id, state, deadline_at, credits_deducted}'
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "smore_draft_batch",
"arguments": {
"platform": "x",
"type": "reply",
"idempotency_key": "mcp-replies-$(date +%s)",
"items": [
{
"thread": [{ "from": "Original post", "body": "Anyone found a good way to see which subreddits talk about their product?" }],
"goal": "Answer helpfully and mention that mention trackers can do this",
"facts": ["A mention tracker counts a term in one subreddit across its full history"]
},
{
"thread": [{ "from": "Original post", "body": "How do you give an agent access to Reddit data?" }],
"goal": "Answer the question and mention that the S'more API has an MCP server",
"facts": ["Reddit mentions, signals and top posts are available as MCP tools"]
}
]
}
}
}
JSON
An agent connected with OAuth calls the tools by name. A good instruction is: "Send these 30 threads to smore_draft_batch as X replies, then check smore_get_draft_batch every poll_after_s seconds until it is done."
Read a batch
GET /api/v1/drafts/batches/{id} needs reddit:posts:read and is free. Read it every poll_after_s seconds until state is done:
BATCH_ID=$(jq -r .batch_id batch.json)
curl -s "https://app.makesmores.com/api/v1/drafts/batches/$BATCH_ID?limit=25" \
-H "Authorization: Bearer $SMORE_API_KEY" \
| jq '{state, counts, poll_after_s, next_after}'
{
"schema_version": 2,
"batch_id": "8c1f0a52-1d7e-4f43-9a55-0f5b8c9d1e20",
"platform": "x",
"type": "reply",
"model": null,
"state": "writing",
"submitted_at": "2026-10-25T19:00:00Z",
"deadline_at": "2026-10-26T03:00:00Z",
"finished_at": null,
"counts": { "total": 3, "queued": 0, "writing": 1, "ready": 2, "failed": 0 },
"price_percent": 50,
"poll_after_s": 30,
"items": [
{
"index": 0,
"draft_id": "1b6f3e2a-7c4d-4e8f-9a1b-2c3d4e5f6a70",
"state": "ready",
"error": null,
"options": [
{
"option": "A",
"model": "x-reply-v1",
"body": "A mention tracker does this. It counts a term in one subreddit across its full history, so you can see where people bring you up.",
"words": 25,
"facts": { "local_check": "pass", "added_numbers": [], "missing_numbers": [], "missing_names": [] }
}
],
"choice": null
},
{ "index": 1, "draft_id": "5d2a9c71-0b3e-4f6a-8d1c-7e9f0a2b3c41", "state": "ready", "error": null, "options": [{ "option": "A", "...": "..." }], "choice": null },
{ "index": 2, "draft_id": "9e4b1d83-2c5f-4a7b-b0e2-8f1a3c5d7e92", "state": "writing", "error": null, "options": [], "choice": null }
],
"next_after": null,
"fact_check": { "checked_by_smore": "numbers_and_names", "how": "..." },
"notice": "...",
"content_notice": "..."
}
| Field | Meaning |
|---|---|
state | queued until an item starts, writing while any item is open, done once every item is ready or failed |
counts | Items by state: total, queued, writing, ready and failed |
finished_at | When the batch reached done, or null |
price_percent | The share of the standard rate the batch pays |
poll_after_s | Seconds to wait before the next read |
items | This page of items in index order. Each has its index, draft_id, state (queued, writing, ready or failed), error with its code when it failed, options, the same options a single draft of this kind returns, and choice once a pick is recorded |
next_after | The after for the next page, or null on the last page |
fact_check, notice, content_notice | The rubric for checking each option before you show it, and the notices a draft read carries |
Read every page
Items come in pages by index. after is an item index, and the read returns the items after it: the default -1 starts at the first item. limit is 25 by default and at most 100. Pass next_after back as after until it is null:
BATCH_ID=$(jq -r .batch_id batch.json)
after=-1
while :; do
page=$(curl -s "https://app.makesmores.com/api/v1/drafts/batches/$BATCH_ID?after=$after&limit=100" \
-H "Authorization: Bearer $SMORE_API_KEY")
echo "$page" | jq -c '.items[]? | {index, state, first_option: .options[0].body}'
after=$(echo "$page" | jq -r '.next_after // empty')
if [ -z "$after" ] || [ "$(echo "$page" | jq '.items | length')" = 0 ]; then break; fi
done
To wait for the whole batch, read one item at a time until state is done. This can take up to 8 hours:
BATCH_ID=$(jq -r .batch_id batch.json)
while :; do
read=$(curl -s "https://app.makesmores.com/api/v1/drafts/batches/$BATCH_ID?limit=1" \
-H "Authorization: Bearer $SMORE_API_KEY")
[ "$(echo "$read" | jq -r .state)" = done ] && break
sleep "$(echo "$read" | jq -r '.poll_after_s // 60')"
done
Read over MCP
smore_get_draft_batch takes batch_id and an optional after and limit, and returns the same read:
jq -n --arg id "$(jq -r .batch_id batch.json)" \
'{jsonrpc: "2.0", id: 1, method: "tools/call", params: {name: "smore_get_draft_batch", arguments: {batch_id: $id, limit: 25}}}' \
| curl -s https://app.makesmores.com/api/v1/mcp \
-H "Authorization: Bearer $SMORE_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d @- \
| sed -n -e 's/^data: //' -e '/^{/p' \
| jq '.result.structuredContent | {state, counts, next_after}'
Pick and post
Each item is an ordinary draft. GET /api/v1/drafts/{id} or smore_get_draft with its draft_id returns its full read, with the platform's block, fact_check and, for Reddit, ai_policy and open_url. Record the pick with POST /api/v1/drafts/{id}/choice or smore_choose_draft, as for any draft, and the console lists batch items with your other drafts. Reading a draft and recording a choice are free.
DRAFT_ID=$(jq -r '.drafts[0].draft_id' batch.json)
curl -s "https://app.makesmores.com/api/v1/drafts/$DRAFT_ID/choice" \
-H "Authorization: Bearer $SMORE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"option": "A"}'
The person then copies the option they picked into X, Reddit or their email.
Examples
Each example writes the batch body to a file, sends it over REST, then sends the same body over MCP with a fresh key. Over MCP the body is the tool's arguments. Every batch here costs credits at the batch rate.
X replies
Take up to ten fresh posts worth a reply from X signals and reply to all of them in one batch. The jq step drops links, bare domains and brackets from each post and keeps its first 1,000 characters, since no thread message may hold a link or a [slot]. It falls back to one sample post when none come back. X replies does the same for a single draft.
curl -s https://app.makesmores.com/api/v1/mcp \
-H "Authorization: Bearer $SMORE_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {"name": "smore_find_x_posts", "arguments": {"worth_reply_only": true, "limit": 10}}}' \
| sed -n -e 's/^data: //' -e '/^{/p' \
| jq --arg key "fresh-replies-$(date +%s)" \
--arg fact "Mention trackers count a term in a subreddit across its full history" '
[.result.structuredContent.posts[]?.text_untrusted // empty
| gsub("https?://\\S+"; "") | gsub("\\S+\\.[a-z]{2,}\\S*"; "") | gsub("[\\[\\]<>]"; "") | .[0:1000]
| select(test("[A-Za-z]"))]
| if length == 0 then ["What tools do you use to find customers?"] else . end
| {platform: "x", type: "reply", idempotency_key: $key,
items: [.[] | {thread: [{from: "Original post", body: .}], goal: "Add one useful point to the conversation", facts: [$fact]}]}' \
> x-replies-batch.json
curl -s https://app.makesmores.com/api/v1/drafts/batches \
-H "Authorization: Bearer $SMORE_API_KEY" \
-H "Content-Type: application/json" \
-d @x-replies-batch.json
jq --arg key "mcp-fresh-replies-$(date +%s)" \
'{jsonrpc: "2.0", id: 1, method: "tools/call", params: {name: "smore_draft_batch", arguments: (.idempotency_key = $key)}}' \
x-replies-batch.json \
| curl -s https://app.makesmores.com/api/v1/mcp \
-H "Authorization: Bearer $SMORE_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d @- \
| sed -n -e 's/^data: //' -e '/^{/p' \
| jq '.result.structuredContent | {batch_id, items, deadline_at}'
X posts
A week of posts, one topic each. The second item asks for two options.
cat > x-posts-batch.json <<JSON
{
"platform": "x",
"type": "post",
"idempotency_key": "week-of-posts-$(date +%s)",
"items": [
{
"topic": "Our public API is open today",
"audience": "Developers who build agents",
"facts": ["One key reaches every product over REST and MCP"]
},
{
"topic": "What we learned reading 1,200 support tickets",
"facts": ["1,200 tickets from September", "41% were about exporting data"],
"count": 2
},
{
"topic": "Why we price drafts per token",
"facts": ["Writers bill per token, counting every candidate", "A failed draft is refunded in full"]
}
]
}
JSON
curl -s https://app.makesmores.com/api/v1/drafts/batches \
-H "Authorization: Bearer $SMORE_API_KEY" \
-H "Content-Type: application/json" \
-d @x-posts-batch.json
jq --arg key "mcp-week-of-posts-$(date +%s)" \
'{jsonrpc: "2.0", id: 1, method: "tools/call", params: {name: "smore_draft_batch", arguments: (.idempotency_key = $key)}}' \
x-posts-batch.json \
| curl -s https://app.makesmores.com/api/v1/mcp \
-H "Authorization: Bearer $SMORE_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d @- \
| sed -n -e 's/^data: //' -e '/^{/p' \
| jq '.result.structuredContent | {batch_id, items, deadline_at}'
Reddit posts
Two plans for r/running. With model left out, each item gets one option from each writer, labelled A, B and C with the model hidden until you record a choice, and counts as three sends toward the limits.
cat > reddit-posts-batch.json <<JSON
{
"platform": "reddit",
"type": "post",
"idempotency_key": "running-posts-$(date +%s)",
"items": [
{
"subreddit": "running",
"plan": {
"format": "personal experience, text only",
"length_words": 120,
"angle": "Cut a 10k time by four minutes in twelve weeks by adding one interval session a week",
"points": [
{ "point": "Added one interval session a week", "evidence": "6 x 800m at 5k pace every Tuesday" },
{ "point": "Ran a faster 10k", "evidence": "48:10 down to 44:05" }
],
"author_specifics": ["Started running two years ago"],
"closing": "ask readers what single change helped their 10k most"
}
},
{
"subreddit": "running",
"plan": {
"format": "question, text only",
"length_words": 90,
"angle": "Asking how others fit long runs into a week with two young kids",
"points": [
{ "point": "Long runs now start at 5:30 on Saturdays", "evidence": "back home by 7:30" },
{ "point": "Weekday runs moved to lunch breaks", "evidence": "three 40-minute runs" }
],
"author_specifics": ["Two kids under four"],
"closing": "ask what schedules have worked for other parents"
}
}
]
}
JSON
curl -s https://app.makesmores.com/api/v1/drafts/batches \
-H "Authorization: Bearer $SMORE_API_KEY" \
-H "Content-Type: application/json" \
-d @reddit-posts-batch.json
Over MCP, this one pins ember-v1 for the whole batch, so each item is one send and returns up to count options from that writer:
jq --arg key "mcp-running-posts-$(date +%s)" \
'{jsonrpc: "2.0", id: 1, method: "tools/call", params: {name: "smore_draft_batch",
arguments: (.idempotency_key = $key | .model = "ember-v1" | .items |= map(.count = 2))}}' \
reddit-posts-batch.json \
| curl -s https://app.makesmores.com/api/v1/mcp \
-H "Authorization: Bearer $SMORE_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d @- \
| sed -n -e 's/^data: //' -e '/^{/p' \
| jq '.result.structuredContent | {batch_id, model, items, deadline_at}'
Read each item's draft before posting. Its ai_policy and rules_to_check_untrusted say what to confirm with the person. A subreddit whose rules may ban AI-written posts needs confirm_rules_allow_ai: true on that item, as on a single draft.
Reddit replies
Each item is a subreddit and a thread, oldest first, as for one Reddit reply:
cat > reddit-replies-batch.json <<JSON
{
"platform": "reddit",
"type": "reply",
"idempotency_key": "running-replies-$(date +%s)",
"items": [
{
"subreddit": "running",
"thread": [
{ "from": "slow_and_steady", "title": "How did you pace your first half marathon?", "body": "Race is in six weeks and I have no idea what pace to start at." },
{ "from": "trail_tom", "body": "Start a little slower than goal pace and pick it up after 15 km." },
{ "from": "slow_and_steady", "body": "What if I don't really have a goal pace yet?" }
]
},
{
"subreddit": "running",
"thread": [
{ "from": "new_to_this", "title": "Shin pain after two weeks of running", "body": "Is this normal or should I stop?" }
]
}
]
}
JSON
curl -s https://app.makesmores.com/api/v1/drafts/batches \
-H "Authorization: Bearer $SMORE_API_KEY" \
-H "Content-Type: application/json" \
-d @reddit-replies-batch.json
jq --arg key "mcp-running-replies-$(date +%s)" \
'{jsonrpc: "2.0", id: 1, method: "tools/call", params: {name: "smore_draft_batch", arguments: (.idempotency_key = $key)}}' \
reddit-replies-batch.json \
| curl -s https://app.makesmores.com/api/v1/mcp \
-H "Authorization: Bearer $SMORE_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d @- \
| sed -n -e 's/^data: //' -e '/^{/p' \
| jq '.result.structuredContent'
Emails
One cold email for each person on a list, from the same sender. Every item has its own to, goal and facts. Newsletters and blog posts, written or rewritten, batch the same way with their own platform and type.
cat > emails-batch.json <<JSON
{
"platform": "email",
"type": "outreach",
"idempotency_key": "wholesale-list-$(date +%s)",
"items": [
{
"to": { "name": "Priya Shah", "role": "Head of Growth", "company": "Northwind Coffee" },
"from": { "name": "Sam Lee", "company": "Roastline" },
"goal": "Ask for a short call about wholesale beans for their cafes",
"facts": ["Roastline roasts to order every Tuesday and Friday", "Northwind opened its third cafe this month"]
},
{
"to": { "name": "Tom Okafor", "role": "Owner", "company": "Corner Bakehouse" },
"from": { "name": "Sam Lee", "company": "Roastline" },
"goal": "Offer a free sample box of espresso beans",
"facts": ["A free sample box holds three 250 g bags", "Wholesale orders ship within two days of roasting"],
"length_words": 70
}
]
}
JSON
curl -s https://app.makesmores.com/api/v1/drafts/batches \
-H "Authorization: Bearer $SMORE_API_KEY" \
-H "Content-Type: application/json" \
-d @emails-batch.json
jq --arg key "mcp-wholesale-list-$(date +%s)" \
'{jsonrpc: "2.0", id: 1, method: "tools/call", params: {name: "smore_draft_batch", arguments: (.idempotency_key = $key)}}' \
emails-batch.json \
| curl -s https://app.makesmores.com/api/v1/mcp \
-H "Authorization: Bearer $SMORE_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d @- \
| sed -n -e 's/^data: //' -e '/^{/p' \
| jq '.result.structuredContent | {batch_id, items, deadline_at}'
Price
A batch pays half the writer's standard per-token rate. S'more stores that share with the batch as price_percent when you submit, so a price change after that never reprices it. As for single drafts, the submit deducts the most each item could cost, each item settles at the tokens it used and is rounded up once with the usual 1-credit minimum, and a failed item is refunded in full.
| Slug | What it does | Input / 1M | Batch input / 1M | Output / 1M | Batch output / 1M | Status |
|---|---|---|---|---|---|---|
ember-v1 | Reddit post writer | $55,000 credits | $2.502,500 credits | $150150,000 credits | $7575,000 credits | Live |
ember-14k | Reddit post writer, 14k | $55,000 credits | $2.502,500 credits | $150150,000 credits | $7575,000 credits | Live |
ember-28k | Reddit post writer, 28k | $55,000 credits | $2.502,500 credits | $150150,000 credits | $7575,000 credits | Live |
ember-reply-v1 | Reddit reply writer | $55,000 credits | $2.502,500 credits | $150150,000 credits | $7575,000 credits | Live |
x-writer-v1 | X post writer | $55,000 credits | $2.502,500 credits | $150150,000 credits | $7575,000 credits | Live |
x-reply-v1 | X reply writer | $55,000 credits | $2.502,500 credits | $150150,000 credits | $7575,000 credits | Live |
prose-1 | Email, newsletter and blog writer | $55,000 credits | $2.502,500 credits | $150150,000 credits | $7575,000 credits | Live |
An X reply that used 179 input and 550 output tokens costs 84 credits ($0.084 at list) as a single draft and 42 credits ($0.042 at list) in a batch.
| Item | Tokens | Single draft | In a batch |
|---|---|---|---|
| X reply | 179 in, 550 out | 84 credits ($0.084 at list) | 42 credits ($0.042 at list) |
| 50 X replies | 179 in, 550 out each | 4,200 credits ($4.20 at list) | 2,100 credits ($2.10 at list) |
| Reddit post, three writers | 1,050 in, 8,880 out | 1,338 credits ($1.34 at list) | 669 credits ($0.669 at list) |
prose-1 email, 8 candidates | 500 in, 800 out | 123 credits ($0.123 at list) | 62 credits ($0.062 at list) |
GET /api/v1/models shows each writer's batch rate in price.batch, and Credits has the formula.
Prices on this site were read from GET /api/v1/models on 2026-10-26.
Limits
| Limit | Value |
|---|---|
| Items per batch | 1 to 200, all with one platform and type |
| Request body | 1 MiB; send a larger set as more than one batch |
| Open batch sends per workspace | 600 |
| Open batch sends across S'more | 1,000 on each GPU pool |
A send is one writing job on a GPU. A Reddit post item without model is three sends, one per writer, and every other item is one. An item counts while it is queued or writing. A batch that would take either count over its limit answers 429 batch_queue_full and stores nothing; send it again later.
Batch items do not count toward the single-draft limits (5 drafts open at once per workspace), so a batch never blocks single drafts. Rate limits has every limit.
Errors
S'more checks each item with the same rules and codes as a single draft. If any item fails, the answer is that item's code with item set to its index, and nothing is stored or charged. Over MCP the tool error's message starts with the index instead, as in Item 7: The request breaks the content rules.:
{
"code": "content_invalid",
"message": "The request breaks the content rules.",
"item": 7,
"details": [{ "field": "thread[0].body", "rule": "no_link" }]
}
| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_request | A missing or unknown field, a duplicate key or a null, in the batch or in an item |
| 400 | model_coming_soon | That writer is coming soon. Nothing was stored or charged |
| 402 | credits_required | The batch's deduction, every item's most possible cost added up, is more than the workspace or the key's cap allows. Nothing was stored |
| 404 | batch_not_found | No batch with that id in this workspace |
| 409 | idempotency_conflict | That key was used for a batch with different items. Send a new key for new work |
| 409 | drafts_off | Drafting or batches are switched off for now. If batches are switched off while items wait, those items fail with drafts_off and are refunded |
| 409, 422 | An item's code, with item | The codes a single draft answers, such as ai_policy_unconfirmed, plan_invalid, email_invalid or content_invalid |
| 429 | batch_queue_full | Too much batch work is waiting, in this workspace or across S'more. Nothing was stored. Send the batch again later |
A failed item has state: "failed" and an error.code: batch_deadline_missed when it was not written by deadline_at, or a single draft's failure code such as no_clean_draft. Every failed item is refunded in full. Errors lists the codes for every route.