Send your first campaign
This guide takes you from subscribing to a sent campaign. The hands-on work takes about 30 minutes. Waiting on AWS for SES production access can add up to a day.
Before you start
Section titled “Before you start”- An AWS account where you can create CloudFormation stacks and IAM roles
- DNS access for the domain you send from, for example
example.com - Your physical mailing address, which is legally required in marketing email
1. Subscribe
Section titled “1. Subscribe”Subscribe to Rhino Relay on AWS Marketplace, or use the link in your welcome email if you signed a contract with us directly. On the registration page, enter your company, your email, your AWS region (any region where SES sends email) and your sending domain. We email you an invitation to the console.
2. Install the template in your account
Section titled “2. Install the template in your account”Sign in to the console. On the Setup page, click Launch in your AWS account. If you subscribed through AWS Marketplace, this opens Marketplace’s guided install. Otherwise it opens CloudFormation directly. Either way, everything is filled in.
The template creates data resources only: two DynamoDB tables, three S3 buckets, EventBridge rules that forward SES events and upload notices to us, a Firehose stream and a Glue table for your event archive, a CloudTrail trail (optional) and one IAM role our service uses. It contains no code. See exactly what it creates and every permission it grants.
Tick the IAM acknowledgement and click Create stack. It takes about 3 minutes. Back in the console, click Verify. The first check turns green when we’ve connected.
3. Request SES production access
Section titled “3. Request SES production access”New AWS accounts can only send to verified addresses. In the SES console, open Account dashboard → Request production access, and paste the request text the Setup page gives you. It asks for your plan’s daily quota: 25,000 emails for Starter, 150,000 for Growth or 500,000 for Scale. AWS usually replies within a day.
4. Add your DNS records
Section titled “4. Add your DNS records”The Setup page lists every record: three DKIM CNAMEs, the bounce. MX and SPF records, a DMARC record if you don’t have one, a track. CNAME, and two certificate validation records. Add them at your DNS provider. Each check turns green as it passes, usually within an hour.
5. Create an API key and save your settings
Section titled “5. Create an API key and save your settings”On the API keys page, create a key with the admin scope and copy it. It’s shown only once.
export KEY="ek_..."export BASE="https://api.rhinorelay.com/v1"
curl -X PATCH "$BASE/settings" -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \ -d '{"defaultFromName":"Example Co","defaultFromEmail":"news@example.com","footerAddress":"Example Co, 1 Main St, Springfield, IL 62701, USA"}'
curl "$BASE/health" -H "Authorization: Bearer $KEY"Every check should show "ok": true before you continue.
6. Import your contacts
Section titled “6. Import your contacts”From Mailchimp, with an API key (Mailchimp → Profile → Extras → API keys):
curl -X POST "$BASE/imports/mailchimp" -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \ -d '{"method":"apiKey","apiKey":"<mailchimp-key>","filters":{"engagedWithinDays":365}}'Poll GET $BASE/imports/<id> until the state is dry_run_ready, then read the summary: how many contacts will be imported, how many stay suppressed, and how many were removed by cleaning. If it looks right:
curl -X POST "$BASE/imports/<id>/commit" -H "Authorization: Bearer $KEY" -H 'Idempotency-Key: import-1'The Mailchimp key is stored in your account during the import and deleted when you commit. For a CSV file, use POST /imports/csv and upload to the uploadUrl it returns. That URL points to a bucket in your own account.
7. Create a template and send yourself a test
Section titled “7. Create a template and send yourself a test”curl -X POST "$BASE/templates" -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' -d '{ "name": "October newsletter", "version": { "subject": "Hi {{ contact.fields.FNAME | default: \"there\" }}, here is October", "html": "<p>Hello!</p><p><a href=\"{{ unsubscribe_url }}\">Unsubscribe</a><br>{{ footer_address }}</p>", "fromName": "Example Co", "fromEmail": "news@example.com" }}'
curl -X POST "$BASE/campaigns" -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \ -d '{"name":"October","templateId":"<tp_...>","templateVersion":1,"segment":{},"stagePlan":{"type":"preset","name":"warmup"}}'
curl -X POST "$BASE/campaigns/<cm_...>/test" -H "Authorization: Bearer $KEY" -H 'Idempotency-Key: test-1' \ -H 'Content-Type: application/json' -d '{"to":["you@example.com"]}'Check the test email arrives, and that its unsubscribe link works.
8. Schedule it
Section titled “8. Schedule it”curl -X POST "$BASE/campaigns/<cm_...>/schedule" -H "Authorization: Bearer $KEY" -H 'Idempotency-Key: schedule-1'curl "$BASE/campaigns/<cm_...>/report?by=stage" -H "Authorization: Bearer $KEY"The warmup plan sends to your most engaged 2% first, then 8%, 20%, 30% and 40% a day apart, checking bounces and complaints before each stage. If either gets too high, the campaign pauses itself and emails you.
Next steps
Section titled “Next steps”- Use
stagePlan: { type: "preset", name: "standard" }after your first campaign. - Subscribe to
campaign.completedandcontact.unsubscribedon your own EventBridge bus. - Read the security page to see what our service can access in your account, and how to check it in your CloudTrail.