POST
/v1/campaigns/Create a campaign
Creates a new DRAFT campaign — the same starting point as clicking “New Campaign” in the app. Combined with add-leads and start, this is what makes a full create → add leads → start integration possible entirely through the API.
Trailing slash required
Call this as /v1/campaigns/, not /v1/campaigns — the bare path without a trailing slash 404s before it reaches Stynar's servers at all, for both GET (list) and POST (create). Every other endpoint on this API works with or without a trailing slash; this exact path is the one exception.
Unknown fields are rejected
The request body is validated strictly — any field not listed below returns 400 VALIDATION_FAILED instead of being silently ignored.
Request
| Authorization | Bearer YOUR_API_KEY |
| Content-Type | application/json |
Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | Required | Campaign name, 1–200 characters. |
| senderIds | string[] | Optional | IDs of connected sending accounts to send from, up to 50. |
| object | Optional | Static content: { subject, previewText, body, fromName, fromEmail, replyTo }. Use this or aiPrompt, not both. | |
| aiPrompt | object | Optional | AI-generated content instead of mail: { prompt, promptId, tone, length }. |
| aiModel | string | Optional | Which AI model to use when generating from aiPrompt. |
| abTest | object | Optional | { enabled, variantB?: { subject, body } } — A/B test a second subject/body variant. |
| scheduleType | enum | Optional | now | schedule | gradual — how sending is paced. Defaults to sending as soon as started. |
| timezone | string | Optional | IANA zone (e.g. America/New_York) — used by 'schedule' and 'gradual'. |
| scheduleStartDate | string | Optional | Start date-time for 'schedule' and 'gradual'. |
| scheduleEndDate | string | Optional | End date-time for 'schedule' and 'gradual'. |
| gradualSettings | object | Optional | Required when scheduleType is 'gradual': { startingVolume, increment, safetyThreshold, sendOnSpecificDays, selectedWeekdays }. |
| sendMode | enum | Optional | direct | draft — 'draft' isn't supported together with scheduleType: 'gradual'. |
curl -X POST "https://api.stynar.com/v1/campaigns/" \
-H "Authorization: Bearer esk_your_key_here" \
-H "Content-Type: application/json" \
-d '{"name":"Q3 outbound","mail":{"subject":"Quick question about {{company}}","body":"<p>Hi {{firstName}},</p>..."}}'With a sender, A/B test, and a gradual schedule
curl -X POST "https://api.stynar.com/v1/campaigns/" \
-H "Authorization: Bearer esk_your_key_here" \
-H "Content-Type: application/json" \
-d '{"name":"Q3 outbound - gradual ramp","senderIds":["sender_abc123"],"mail":{"subject":"Quick question about {{company}}","body":"<p>Hi {{firstName}},</p>..."},"abTest":{"enabled":true,"variantB":{"subject":"{{firstName}}, quick question"}},"scheduleType":"gradual","timezone":"America/New_York","gradualSettings":{"startingVolume":20,"increment":5,"safetyThreshold":"bounce_rate","sendOnSpecificDays":true,"selectedWeekdays":["Monday","Tuesday","Wednesday","Thursday","Friday"]}}'Response
✓ 201 Created
201 response
{
"campaign": {
"campaignId": "cmp_abc123",
"name": "Q3 outbound",
"status": "DRAFT",
"senderIds": [],
"mail": {
"subject": "Quick question about {{company}}",
"body": "<p>Hi {{firstName}},</p>..."
},
"createdAt": "2026-08-16T10:02:11Z"
}
}Response fields
Errors
| Status | Code | Meaning |
|---|---|---|
| ✕ 401 Unauthorized | UNAUTHORIZED | Missing, malformed, unknown, revoked, or expired key. |
| ✕ 403 Forbidden | API_ACCESS_DISABLED | Your account doesn't currently have API access. |
| ✕ 403 Forbidden | INSUFFICIENT_SCOPE | The key doesn't have the scope this endpoint requires. |
| ✕ 404 Not Found | NOT_FOUND | Unknown route, or a resource that doesn't exist / isn't yours. |
| ✕ 409 Conflict | CONFLICT | The action can't be applied to the resource's current state. |
| ✕ 429 Too Many Requests | RATE_LIMIT_EXCEEDED | Per-minute or per-second limit hit. |
| ✕ 429 Too Many Requests | QUOTA_EXCEEDED | Monthly quota exhausted. |
| ✕ 500 Internal Server Error | INTERNAL_ERROR | Something broke on Stynar's end. |