curl -X POST https://win.oneshotagent.com/v1/tools/physical-mail/send \
-H "Content-Type: application/json" \
-H "X-Agent-ID: 0xYourWalletAddress" \
-H "x-agent-proof: <base64 signed proof, scope=submit>" \
-H "Idempotency-Key: thank-you-2026-q3-jane-doe" \
-d '{
"quote_id": "00000000-0000-4000-8000-000000000000",
"approval_id": "00000000-0000-4000-8000-000000000000",
"memo": "Q3 customer thank-you letter"
}'
import { OneShot } from "@oneshot-agent/sdk";
const agent = new OneShot({ privateKey: process.env.AGENT_PRIVATE_KEY });
const order = await agent.physicalMail.send({
quote_id: approval.quote_id,
approval_id: approval.approval_id,
idempotencyKey: savedKey, // saved before this call
maxCost: Number(quote.total_usdc),
memo: "Q3 customer thank-you letter",
});
order = client.physical_mail.send(
quote_id=approval["quote_id"],
approval_id=approval["approval_id"],
idempotency_key=saved_key,
max_cost=float(quote["total_usdc"]),
memo="Q3 customer thank-you letter",
)
{
"order_id": "00000000-0000-4000-8000-000000000000",
"quote_id": "00000000-0000-4000-8000-000000000000",
"order_status": "pending",
"payment_status": "pending",
"fulfillment_status": "pending",
"receipt_id": "rcpt_...",
"signed_receipt": null,
"total_usdc": "<the quote's total_usdc>",
"idempotency_key": "thank-you-2026-q3-jane-doe",
"events": [],
"cancellation_requested": false,
"cancellation_error": null,
"cancel_before": null,
"refunded_at": null,
"delivery_proves_readership": false
}
{
"error": "insufficient_credits",
"required_usdc": "<the quote's total_usdc>",
"credits_balance": "<your credits balance>",
"shortfall_usdc": "<required_usdc minus credits_balance>",
"quote_id": "00000000-0000-4000-8000-000000000000"
}
{
"error": "approval_required",
"status": "pending_approval",
"message": "This physical_mail call needs a human approval (rule <rule id>). It was not run or charged. Retry the same call with X-Approval-Id once approved.",
"approval_id": "<policy approval id>",
"approval": { "...": "the pending approval" }
}
{
"error": "approval_required_or_expired"
}
Physical Mail
Send an approved mailpiece
Purchase an individually approved letter or postcard
POST
/
v1
/
tools
/
physical-mail
/
send
curl -X POST https://win.oneshotagent.com/v1/tools/physical-mail/send \
-H "Content-Type: application/json" \
-H "X-Agent-ID: 0xYourWalletAddress" \
-H "x-agent-proof: <base64 signed proof, scope=submit>" \
-H "Idempotency-Key: thank-you-2026-q3-jane-doe" \
-d '{
"quote_id": "00000000-0000-4000-8000-000000000000",
"approval_id": "00000000-0000-4000-8000-000000000000",
"memo": "Q3 customer thank-you letter"
}'
import { OneShot } from "@oneshot-agent/sdk";
const agent = new OneShot({ privateKey: process.env.AGENT_PRIVATE_KEY });
const order = await agent.physicalMail.send({
quote_id: approval.quote_id,
approval_id: approval.approval_id,
idempotencyKey: savedKey, // saved before this call
maxCost: Number(quote.total_usdc),
memo: "Q3 customer thank-you letter",
});
order = client.physical_mail.send(
quote_id=approval["quote_id"],
approval_id=approval["approval_id"],
idempotency_key=saved_key,
max_cost=float(quote["total_usdc"]),
memo="Q3 customer thank-you letter",
)
{
"order_id": "00000000-0000-4000-8000-000000000000",
"quote_id": "00000000-0000-4000-8000-000000000000",
"order_status": "pending",
"payment_status": "pending",
"fulfillment_status": "pending",
"receipt_id": "rcpt_...",
"signed_receipt": null,
"total_usdc": "<the quote's total_usdc>",
"idempotency_key": "thank-you-2026-q3-jane-doe",
"events": [],
"cancellation_requested": false,
"cancellation_error": null,
"cancel_before": null,
"refunded_at": null,
"delivery_proves_readership": false
}
{
"error": "insufficient_credits",
"required_usdc": "<the quote's total_usdc>",
"credits_balance": "<your credits balance>",
"shortfall_usdc": "<required_usdc minus credits_balance>",
"quote_id": "00000000-0000-4000-8000-000000000000"
}
{
"error": "approval_required",
"status": "pending_approval",
"message": "This physical_mail call needs a human approval (rule <rule id>). It was not run or charged. Retry the same call with X-Approval-Id once approved.",
"approval_id": "<policy approval id>",
"approval": { "...": "the pending approval" }
}
{
"error": "approval_required_or_expired"
}
Overview
Buys the mailpiece a person approved: the quote and its approval, at the approved price. Paid from credits, or by x402. Returns202 with the order. Read the order for its status and the signed receipt, signed on acceptance, cancellation or failure, not delivery.
The Idempotency-Key header is required and never expires. Save the key before you call. The same key with the same body replays the original order with the Idempotent-Replay: true header and sends nothing. After a timeout or a lost response, Recover finds the order by that key instead of sending again.
A piece that reached printing cannot be recalled. Approve from the approver’s handler, never automatically after a preview.
Authentication
X-Agent-ID plus a signed x-agent-proof with scope: "submit", or an access token. See proof authentication. An access-token session pays from credits only and cannot carry a payment header. 60 requests a minute per agent.
Headers
string
required
1 to 255 characters of
[A-Za-z0-9_.:-]. The same key with a different body returns 422 idempotency_key_reuse.string
Refuses the send with
400 max_cost_exceeded when the quote’s total_usdc is above it.string
The
approval_id from a 403 approval_required response, once approved. Repeating the call with it releases the send the action policy held. Not the quote’s approval_id.Request Body
string
required
Quote ID from the preview
Audit fields (optional)
string
Reason for this send, stored on the receipt for audit. Max 1000 characters: a longer memo is rejected with
400 invalid_input before anything is held or charged, not truncated. See Audit Trail.object
Decision metadata for supervisor and auditor agents, stored with the receipt. Open schema; known fields
goal, goalId, alternatives (string[]) and confidence (0-1). Extra keys are stored verbatim.Response
202 with the order. Its fields are listed on Get an order. A replay returns 200 with the same order.
curl -X POST https://win.oneshotagent.com/v1/tools/physical-mail/send \
-H "Content-Type: application/json" \
-H "X-Agent-ID: 0xYourWalletAddress" \
-H "x-agent-proof: <base64 signed proof, scope=submit>" \
-H "Idempotency-Key: thank-you-2026-q3-jane-doe" \
-d '{
"quote_id": "00000000-0000-4000-8000-000000000000",
"approval_id": "00000000-0000-4000-8000-000000000000",
"memo": "Q3 customer thank-you letter"
}'
import { OneShot } from "@oneshot-agent/sdk";
const agent = new OneShot({ privateKey: process.env.AGENT_PRIVATE_KEY });
const order = await agent.physicalMail.send({
quote_id: approval.quote_id,
approval_id: approval.approval_id,
idempotencyKey: savedKey, // saved before this call
maxCost: Number(quote.total_usdc),
memo: "Q3 customer thank-you letter",
});
order = client.physical_mail.send(
quote_id=approval["quote_id"],
approval_id=approval["approval_id"],
idempotency_key=saved_key,
max_cost=float(quote["total_usdc"]),
memo="Q3 customer thank-you letter",
)
{
"order_id": "00000000-0000-4000-8000-000000000000",
"quote_id": "00000000-0000-4000-8000-000000000000",
"order_status": "pending",
"payment_status": "pending",
"fulfillment_status": "pending",
"receipt_id": "rcpt_...",
"signed_receipt": null,
"total_usdc": "<the quote's total_usdc>",
"idempotency_key": "thank-you-2026-q3-jane-doe",
"events": [],
"cancellation_requested": false,
"cancellation_error": null,
"cancel_before": null,
"refunded_at": null,
"delivery_proves_readership": false
}
{
"error": "insufficient_credits",
"required_usdc": "<the quote's total_usdc>",
"credits_balance": "<your credits balance>",
"shortfall_usdc": "<required_usdc minus credits_balance>",
"quote_id": "00000000-0000-4000-8000-000000000000"
}
{
"error": "approval_required",
"status": "pending_approval",
"message": "This physical_mail call needs a human approval (rule <rule id>). It was not run or charged. Retry the same call with X-Approval-Id once approved.",
"approval_id": "<policy approval id>",
"approval": { "...": "the pending approval" }
}
{
"error": "approval_required_or_expired"
}
Errors
| Code | When |
|---|---|
400 invalid_input | Missing Idempotency-Key, a bad body, or a memo over 1000 characters |
400 max_cost_exceeded | Above X-Max-Cost-USDC |
402 payment_required | Pay by x402; a wallet session without enough credits |
402 insufficient_credits | An access-token session without enough credits |
403 approval_required | Held by a require_approval policy rule; nothing sent or charged. Repeat the call, same Idempotency-Key, with X-Approval-Id once approved |
403 action_denied_by_policy | Refused by a deny policy rule; not resumable |
409 approval_required_or_expired | No current approval for this quote |
409 quote_already_ordered | The quote already has an order |
422 idempotency_key_reuse | Same key, different body |
503 moderation_unavailable | Unsent, nothing charged; retry after Retry-After |