Quickstart
Go from zero to sending emails and creating crypto invoices in under 5 minutes.
Create your account
Sign up at clawstack.polsia.app/login. You'll get an API key automatically — copy it from the dashboard.
Send your first email
Hit the email endpoint with your API key. That's it — no SMTP config, no domain verification.
Create a crypto invoice
Accept BTC, ETH, USDC, and 50+ tokens. One API call returns a hosted payment page.
Send your first email
curl -X POST https://clawstack.polsia.app/api/email/send \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"to": "hello@example.com",
"subject": "Hello from ClawStack",
"body": "Your first email is live!"
}'
const response = await fetch("https://clawstack.polsia.app/api/email/send", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": "YOUR_API_KEY"
},
body: JSON.stringify({
to: "hello@example.com",
subject: "Hello from ClawStack",
body: "Your first email is live!"
})
});
const data = await response.json();
console.log(data);
// { success: true, data: { message_id: "abc-123", ... } }
import requests
response = requests.post(
"https://clawstack.polsia.app/api/email/send",
headers={
"Content-Type": "application/json",
"x-api-key": "YOUR_API_KEY"
},
json={
"to": "hello@example.com",
"subject": "Hello from ClawStack",
"body": "Your first email is live!"
}
)
data = response.json()
print(data)
# {"success": True, "data": {"message_id": "abc-123", ...}}
Create your first invoice
curl -X POST https://clawstack.polsia.app/api/payments/create-invoice \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"amount": 49.99,
"currency": "USD",
"order_id": "order_001",
"order_description": "Pro Plan — Monthly"
}'
const response = await fetch("https://clawstack.polsia.app/api/payments/create-invoice", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": "YOUR_API_KEY"
},
body: JSON.stringify({
amount: 49.99,
currency: "USD",
order_id: "order_001",
order_description: "Pro Plan — Monthly"
})
});
const data = await response.json();
console.log(data.data.invoice_url);
// Redirect user to this URL to complete payment
import requests
response = requests.post(
"https://clawstack.polsia.app/api/payments/create-invoice",
headers={
"Content-Type": "application/json",
"x-api-key": "YOUR_API_KEY"
},
json={
"amount": 49.99,
"currency": "USD",
"order_id": "order_001",
"order_description": "Pro Plan — Monthly"
}
)
data = response.json()
print(data["data"]["invoice_url"])
# Redirect user to this URL to complete payment
Authentication
Every API request requires your key in the x-api-key header.
x-api-key: cs_live_a1b2c3d4e5f6...
Get your API key from the dashboard after signing up. You can create up to 5 keys per account — useful for separating dev/staging/prod environments.
Key format
All keys start with cs_live_ followed by 48 hex characters. If your key doesn't match this format, something's wrong.
Test your key
# A valid key returns 200. Invalid returns 401.
curl -s -o /dev/null -w "%{http_code}" \
-X POST https://clawstack.polsia.app/api/email/send \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{"to":"test@test.com","subject":"ping","body":"pong"}'
// Quick auth check — send a test email
const res = await fetch("https://clawstack.polsia.app/api/email/send", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": "YOUR_API_KEY"
},
body: JSON.stringify({
to: "test@test.com",
subject: "ping",
body: "pong"
})
});
console.log(res.status); // 200 = valid, 401 = bad key
# Quick auth check
import requests
res = requests.post(
"https://clawstack.polsia.app/api/email/send",
headers={
"Content-Type": "application/json",
"x-api-key": "YOUR_API_KEY"
},
json={"to": "test@test.com", "subject": "ping", "body": "pong"}
)
print(res.status_code) # 200 = valid, 401 = bad key
Send Email
Send transactional emails through Postmark-backed infrastructure. High deliverability, zero SMTP setup.
Send a transactional email to one or more recipients. Supports plain text and HTML content.
Request body
| Parameter | Type | Description |
|---|---|---|
| to required | string | string[] | Recipient email(s). Single address or array. |
| subject required | string | Email subject line |
| body | string | Plain text body. Provide body and/or html_body. |
| html_body | string | HTML body for rich formatting |
| from_name | string | Sender display name (e.g. "MyApp") |
| tag | string | Tag for analytics and filtering |
Examples
# Send a plain text email
curl -X POST https://clawstack.polsia.app/api/email/send \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"to": "user@example.com",
"subject": "Your receipt",
"body": "Thanks for your purchase! Order #12345."
}'
# Send an HTML email to multiple recipients
curl -X POST https://clawstack.polsia.app/api/email/send \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"to": ["user1@example.com", "user2@example.com"],
"subject": "Weekly Report",
"html_body": "<h1>Weekly Report</h1><p>Here are your metrics...</p>",
"from_name": "Analytics Bot",
"tag": "reports"
}'
const CLAWSTACK_KEY = process.env.CLAWSTACK_API_KEY;
const BASE_URL = "https://clawstack.polsia.app";
// Helper function
async function sendEmail({ to, subject, body, htmlBody, fromName, tag }) {
const res = await fetch(`${BASE_URL}/api/email/send`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": CLAWSTACK_KEY
},
body: JSON.stringify({
to,
subject,
...(body && { body }),
...(htmlBody && { html_body: htmlBody }),
...(fromName && { from_name: fromName }),
...(tag && { tag })
})
});
return res.json();
}
// Plain text email
const result = await sendEmail({
to: "user@example.com",
subject: "Your receipt",
body: "Thanks for your purchase! Order #12345."
});
console.log(result.data.message_id);
// HTML email to multiple recipients
const batch = await sendEmail({
to: ["user1@example.com", "user2@example.com"],
subject: "Weekly Report",
htmlBody: "<h1>Weekly Report</h1><p>Your metrics...</p>",
fromName: "Analytics Bot",
tag: "reports"
});
import os
import requests
CLAWSTACK_KEY = os.environ["CLAWSTACK_API_KEY"]
BASE_URL = "https://clawstack.polsia.app"
def send_email(to, subject, body=None, html_body=None, from_name=None, tag=None):
payload = {"to": to, "subject": subject}
if body:
payload["body"] = body
if html_body:
payload["html_body"] = html_body
if from_name:
payload["from_name"] = from_name
if tag:
payload["tag"] = tag
response = requests.post(
f"{BASE_URL}/api/email/send",
headers={
"Content-Type": "application/json",
"x-api-key": CLAWSTACK_KEY
},
json=payload
)
return response.json()
# Plain text email
result = send_email(
to="user@example.com",
subject="Your receipt",
body="Thanks for your purchase! Order #12345."
)
print(result["data"]["message_id"])
# HTML email to multiple recipients
batch = send_email(
to=["user1@example.com", "user2@example.com"],
subject="Weekly Report",
html_body="<h1>Weekly Report</h1><p>Your metrics...</p>",
from_name="Analytics Bot",
tag="reports"
)
Response
{
"success": true,
"data": {
"message_id": "abc-123-def-456",
"submitted_at": "2026-03-18T12:00:00Z",
"to": ["user@example.com"]
}
}
Create Invoice
Create crypto payment invoices that accept BTC, ETH, USDC, and 50+ tokens via NOWPayments.
Create a hosted payment page. Redirect your user to the returned invoice_url to collect payment.
Request body
| Parameter | Type | Description |
|---|---|---|
| amount required | number | Invoice amount (e.g. 49.99). Must be > 0. |
| currency required | string | Price currency: USD, EUR, BTC, etc. |
| pay_currency | string | Specific crypto to accept (BTC, ETH, USDC). Omit for multi-currency checkout. |
| order_id | string | Your internal order/reference ID |
| order_description | string | Description shown on the payment page |
| success_url | string | Redirect after successful payment |
| cancel_url | string | Redirect if user cancels |
Examples
# Create a USD invoice, payable in any crypto
curl -X POST https://clawstack.polsia.app/api/payments/create-invoice \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"amount": 49.99,
"currency": "USD",
"order_id": "order_abc",
"order_description": "Pro Plan — Monthly",
"success_url": "https://myapp.com/thanks",
"cancel_url": "https://myapp.com/pricing"
}'
# Accept only USDC payments
curl -X POST https://clawstack.polsia.app/api/payments/create-invoice \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"amount": 100,
"currency": "USD",
"pay_currency": "USDC"
}'
const CLAWSTACK_KEY = process.env.CLAWSTACK_API_KEY;
const BASE_URL = "https://clawstack.polsia.app";
async function createInvoice({ amount, currency, payCurrency, orderId, description, successUrl, cancelUrl }) {
const res = await fetch(`${BASE_URL}/api/payments/create-invoice`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": CLAWSTACK_KEY
},
body: JSON.stringify({
amount,
currency,
...(payCurrency && { pay_currency: payCurrency }),
...(orderId && { order_id: orderId }),
...(description && { order_description: description }),
...(successUrl && { success_url: successUrl }),
...(cancelUrl && { cancel_url: cancelUrl })
})
});
return res.json();
}
// Create invoice and redirect user
const invoice = await createInvoice({
amount: 49.99,
currency: "USD",
orderId: "order_abc",
description: "Pro Plan — Monthly",
successUrl: "https://myapp.com/thanks",
cancelUrl: "https://myapp.com/pricing"
});
// Redirect user to payment page
console.log(invoice.data.invoice_url);
// "https://nowpayments.io/payment/..."
import os
import requests
CLAWSTACK_KEY = os.environ["CLAWSTACK_API_KEY"]
BASE_URL = "https://clawstack.polsia.app"
def create_invoice(amount, currency, pay_currency=None, order_id=None,
description=None, success_url=None, cancel_url=None):
payload = {"amount": amount, "currency": currency}
if pay_currency:
payload["pay_currency"] = pay_currency
if order_id:
payload["order_id"] = order_id
if description:
payload["order_description"] = description
if success_url:
payload["success_url"] = success_url
if cancel_url:
payload["cancel_url"] = cancel_url
response = requests.post(
f"{BASE_URL}/api/payments/create-invoice",
headers={
"Content-Type": "application/json",
"x-api-key": CLAWSTACK_KEY
},
json=payload
)
return response.json()
# Create invoice and redirect user
invoice = create_invoice(
amount=49.99,
currency="USD",
order_id="order_abc",
description="Pro Plan — Monthly",
success_url="https://myapp.com/thanks",
cancel_url="https://myapp.com/pricing"
)
print(invoice["data"]["invoice_url"])
# "https://nowpayments.io/payment/..."
Response
{
"success": true,
"data": {
"invoice_id": "inv_abc123",
"invoice_url": "https://nowpayments.io/payment/...",
"status": "pending",
"price_amount": 49.99,
"price_currency": "USD",
"created_at": "2026-03-18T12:00:00Z"
}
}
Check Invoice Status
Poll the status of a payment invoice to confirm payment completion.
Returns the current status of an invoice. Use this to verify payment before fulfilling orders.
Statuses: pending → confirming → confirmed → finished | expired
curl https://clawstack.polsia.app/api/payments/invoice/inv_abc123 \
-H "x-api-key: YOUR_API_KEY"
async function checkInvoice(invoiceId) {
const res = await fetch(
`https://clawstack.polsia.app/api/payments/invoice/${invoiceId}`,
{ headers: { "x-api-key": process.env.CLAWSTACK_API_KEY } }
);
return res.json();
}
const status = await checkInvoice("inv_abc123");
if (status.data.status === "finished") {
console.log("Payment confirmed! Fulfill the order.");
} else {
console.log(`Status: ${status.data.status}`);
}
import os
import requests
def check_invoice(invoice_id):
response = requests.get(
f"https://clawstack.polsia.app/api/payments/invoice/{invoice_id}",
headers={"x-api-key": os.environ["CLAWSTACK_API_KEY"]}
)
return response.json()
status = check_invoice("inv_abc123")
if status["data"]["status"] == "finished":
print("Payment confirmed! Fulfill the order.")
else:
print(f"Status: {status['data']['status']}")
Response
{
"success": true,
"data": {
"invoice_id": "inv_abc123",
"status": "finished",
"price_amount": 49.99,
"price_currency": "USD",
"invoice_url": "https://nowpayments.io/payment/..."
}
}
AI Agent Integration
Wire ClawStack into your AI agent so it can send emails and collect payments autonomously.
Node.js agent with tool functions
Define ClawStack as tool functions your AI agent can call. Works with OpenAI, Anthropic, LangChain, or any framework that supports function calling.
// ClawStack tool definitions for your AI agent
const CLAWSTACK_KEY = process.env.CLAWSTACK_API_KEY;
const BASE = "https://clawstack.polsia.app";
const clawstackTools = {
send_email: {
description: "Send a transactional email to a user",
parameters: {
to: { type: "string", description: "Recipient email" },
subject: { type: "string", description: "Subject line" },
body: { type: "string", description: "Email body (plain text or HTML)" }
},
execute: async ({ to, subject, body }) => {
const res = await fetch(`${BASE}/api/email/send`, {
method: "POST",
headers: { "Content-Type": "application/json", "x-api-key": CLAWSTACK_KEY },
body: JSON.stringify({ to, subject, html_body: body })
});
return res.json();
}
},
create_invoice: {
description: "Create a crypto payment invoice",
parameters: {
amount: { type: "number", description: "Amount in USD" },
order_id: { type: "string", description: "Your order reference" },
description: { type: "string", description: "What the payment is for" }
},
execute: async ({ amount, order_id, description }) => {
const res = await fetch(`${BASE}/api/payments/create-invoice`, {
method: "POST",
headers: { "Content-Type": "application/json", "x-api-key": CLAWSTACK_KEY },
body: JSON.stringify({
amount,
currency: "USD",
order_id,
order_description: description
})
});
return res.json();
}
}
};
// Usage with OpenAI function calling
const tools = Object.entries(clawstackTools).map(([name, tool]) => ({
type: "function",
function: {
name,
description: tool.description,
parameters: {
type: "object",
properties: tool.parameters,
required: Object.keys(tool.parameters)
}
}
}));
// When the model calls a tool:
async function handleToolCall(name, args) {
return clawstackTools[name].execute(args);
}
import os
import requests
import json
CLAWSTACK_KEY = os.environ["CLAWSTACK_API_KEY"]
BASE = "https://clawstack.polsia.app"
HEADERS = {"Content-Type": "application/json", "x-api-key": CLAWSTACK_KEY}
# Tool functions your agent can call
def send_email(to: str, subject: str, body: str) -> dict:
"""Send a transactional email to a user."""
return requests.post(f"{BASE}/api/email/send", headers=HEADERS, json={
"to": to, "subject": subject, "html_body": body
}).json()
def create_invoice(amount: float, order_id: str, description: str) -> dict:
"""Create a crypto payment invoice."""
return requests.post(f"{BASE}/api/payments/create-invoice", headers=HEADERS, json={
"amount": amount, "currency": "USD",
"order_id": order_id, "order_description": description
}).json()
# OpenAI function calling schema
tools = [
{
"type": "function",
"function": {
"name": "send_email",
"description": "Send a transactional email to a user",
"parameters": {
"type": "object",
"properties": {
"to": {"type": "string", "description": "Recipient email"},
"subject": {"type": "string", "description": "Subject line"},
"body": {"type": "string", "description": "Email body (HTML)"}
},
"required": ["to", "subject", "body"]
}
}
},
{
"type": "function",
"function": {
"name": "create_invoice",
"description": "Create a crypto payment invoice",
"parameters": {
"type": "object",
"properties": {
"amount": {"type": "number", "description": "Amount in USD"},
"order_id": {"type": "string", "description": "Order reference"},
"description": {"type": "string", "description": "What the payment is for"}
},
"required": ["amount", "order_id", "description"]
}
}
}
]
# Handle tool calls from the model
TOOL_MAP = {"send_email": send_email, "create_invoice": create_invoice}
def handle_tool_call(name: str, args: dict) -> dict:
return TOOL_MAP[name](**args)
Full agent example: invoice + receipt email
A common pattern — create an invoice, then email the payment link to the customer.
const CLAWSTACK_KEY = process.env.CLAWSTACK_API_KEY;
const BASE = "https://clawstack.polsia.app";
const headers = { "Content-Type": "application/json", "x-api-key": CLAWSTACK_KEY };
async function chargeCustomer(email, amount, orderId, productName) {
// 1. Create the invoice
const invoiceRes = await fetch(`${BASE}/api/payments/create-invoice`, {
method: "POST", headers,
body: JSON.stringify({
amount,
currency: "USD",
order_id: orderId,
order_description: productName,
success_url: `https://myapp.com/orders/${orderId}/thanks`
})
});
const invoice = await invoiceRes.json();
if (!invoice.success) throw new Error(invoice.error);
// 2. Email the payment link
const emailRes = await fetch(`${BASE}/api/email/send`, {
method: "POST", headers,
body: JSON.stringify({
to: email,
subject: `Invoice for ${productName}`,
html_body: `
<h2>Your invoice is ready</h2>
<p>Amount: $${amount} USD</p>
<p><a href="${invoice.data.invoice_url}">Pay Now</a></p>
`,
from_name: "MyApp Billing",
tag: "invoices"
})
});
return { invoice: invoice.data, email: (await emailRes.json()).data };
}
// Usage
await chargeCustomer("buyer@example.com", 99, "ord_789", "Annual Plan");
import os
import requests
CLAWSTACK_KEY = os.environ["CLAWSTACK_API_KEY"]
BASE = "https://clawstack.polsia.app"
HEADERS = {"Content-Type": "application/json", "x-api-key": CLAWSTACK_KEY}
def charge_customer(email, amount, order_id, product_name):
# 1. Create the invoice
invoice_res = requests.post(f"{BASE}/api/payments/create-invoice", headers=HEADERS, json={
"amount": amount,
"currency": "USD",
"order_id": order_id,
"order_description": product_name,
"success_url": f"https://myapp.com/orders/{order_id}/thanks"
}).json()
if not invoice_res["success"]:
raise Exception(invoice_res["error"])
payment_url = invoice_res["data"]["invoice_url"]
# 2. Email the payment link
email_res = requests.post(f"{BASE}/api/email/send", headers=HEADERS, json={
"to": email,
"subject": f"Invoice for {product_name}",
"html_body": f"""
<h2>Your invoice is ready</h2>
<p>Amount: ${amount} USD</p>
<p><a href="{payment_url}">Pay Now</a></p>
""",
"from_name": "MyApp Billing",
"tag": "invoices"
}).json()
return {"invoice": invoice_res["data"], "email": email_res["data"]}
# Usage
result = charge_customer("buyer@example.com", 99, "ord_789", "Annual Plan")
print(result["invoice"]["invoice_url"])
Error Handling
All errors return a consistent JSON shape. Check success first, then handle the HTTP status code.
// Every error response looks like this:
{
"success": false,
"error": "Description of what went wrong"
}
// Rate limit errors include extra fields:
{
"success": false,
"error": "Rate limit exceeded",
"limit": 60,
"retry_after_seconds": 60
}
Status codes
| 200 | Success |
| 400 | Bad request — missing or invalid parameters |
| 401 | Unauthorized — missing or invalid API key |
| 403 | Forbidden — API key deactivated |
| 429 | Rate limit exceeded — wait and retry |
| 502 | Upstream error — provider issue, retry in a few seconds |
Handling errors in code
async function clawstackRequest(endpoint, body) {
const res = await fetch(`https://clawstack.polsia.app${endpoint}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": process.env.CLAWSTACK_API_KEY
},
body: JSON.stringify(body)
});
const data = await res.json();
if (!data.success) {
if (res.status === 429) {
// Rate limited — wait and retry
const wait = (data.retry_after_seconds || 60) * 1000;
await new Promise(r => setTimeout(r, wait));
return clawstackRequest(endpoint, body); // retry once
}
throw new Error(`ClawStack ${res.status}: ${data.error}`);
}
return data;
}
import time
import requests
import os
def clawstack_request(endpoint, body):
res = requests.post(
f"https://clawstack.polsia.app{endpoint}",
headers={
"Content-Type": "application/json",
"x-api-key": os.environ["CLAWSTACK_API_KEY"]
},
json=body
)
data = res.json()
if not data["success"]:
if res.status_code == 429:
# Rate limited — wait and retry
wait = data.get("retry_after_seconds", 60)
time.sleep(wait)
return clawstack_request(endpoint, body) # retry once
raise Exception(f"ClawStack {res.status_code}: {data['error']}")
return data
Rate Limits
ClawStack enforces per-key rate limiting to keep the platform stable.
| Limit | Value | Details |
|---|---|---|
| Requests | 60/min | Per API key. Shared across all endpoints. |
| Email recipients | No limit* | Each recipient in a batch counts as 1 request toward rate limit. |
| API keys | 5 per account | Create separate keys for dev/staging/prod. |