API REFERENCE · V2

Fernway REST API

Every endpoint takes JSON and returns JSON. Authenticate with a bearer key, and pin a version with the Fernway-Version header. All examples use placeholder keys and a fictional host.

v2 · current

v1 · deprecated

https://api.fernway.example/v2

→

Still on v1?

v1 endpoints keep working until the retirement date in the migration guide. New fields are only added to v2.

POST

/v2/messages

Send a message

Queues one message on SMS, email or push. Returns immediately with a queued message; delivery updates arrive by webhook.

PARAMETERS

to

string · required

Phone number, email address or device token.

channel

enum · required

sms, email or push.

body

string · required

Message text. Email also accepts html.

send_at

timestamp · optional

Schedule up to 30 days ahead.

curl https://api.fernway.example/v2/messages \
-H "Authorization: Bearer $FERNWAY_API_KEY" \
-H "Idempotency-Key: 4f1c-demo" \
-d '{"to":"+15555550123","channel":"sms","body":"Your code is 482913"}'
202 AcceptedResponse41 ms
{
"id": "msg_01HZX3DEMO",
"status": "queued",
"channel": "sms",
"to": "+15555550123",
"created_at": "2026-10-20T14:02:11Z"
}

GET

/v2/messages/{id}

Retrieve a message

Fetches one message with its latest delivery status and the timestamps for each attempt.

PARAMETERS

id

string · path

The message ID, for example msg_01HZX3DEMO.

curl https://api.fernway.example/v2/messages/msg_01HZX3DEMO \
-H "Authorization: Bearer $FERNWAY_API_KEY"
200 OKResponse18 ms
{
"id": "msg_01HZX3DEMO",
"status": "delivered",
"attempts": 1,
"delivered_at": "2026-10-20T14:02:13Z"
}

GET

/v2/messages

List messages

Returns messages newest first. Pages are cursor-based: pass next_cursor back as cursor to get the next page.

PARAMETERS

limit

integer · optional

1 to 100. Defaults to 25.

cursor

string · optional

From the previous response.

status

enum · optional

Filter by queued, sent, delivered or failed.

curl "https://api.fernway.example/v2/messages?limit=2" \
-H "Authorization: Bearer $FERNWAY_API_KEY"
200 OKResponse27 ms
{
"data": [{ "id": "msg_01HZX3DEMO", "status": "delivered" }],
"next_cursor": "cur_9QDEMO",
"has_more": true
}

PATCH

/v2/webhooks/{id}

Update a webhook

Changes the URL or the event types a webhook endpoint receives. The signing secret stays the same.

PARAMETERS

url

string · optional

HTTPS URL that receives events.

events

array · optional

For example message.delivered, message.failed.

curl -X PATCH https://api.fernway.example/v2/webhooks/wh_42DEMO \
-H "Authorization: Bearer $FERNWAY_API_KEY" \
-d '{"events":["message.delivered","message.failed"]}'
200 OKResponse33 ms
{
"id": "wh_42DEMO",
"url": "https://example.com/hooks/fernway",
"events": ["message.delivered", "message.failed"]
}

DELETE

/v2/messages/{id}

Cancel a scheduled message

Cancels a message that has a send_at in the future. Messages already sent cannot be cancelled.

PARAMETERS

id

string · path

The scheduled message ID.

curl -X DELETE https://api.fernway.example/v2/messages/msg_01HZX3DEMO \
-H "Authorization: Bearer $FERNWAY_API_KEY"
409 ConflictResponse12 ms
{
"error": {
"code": "message_already_sent",
"message": "This message was sent and can no longer be cancelled."
}
}

Errors

Errors use standard HTTP status codes and a stable code string. Quote the request_id when you contact support.

400

invalid_request

401

invalid_api_key

409

message_already_sent

429

rate_limited

500

internal_error

Create a free website with Framer, the website builder loved by startups, designers and agencies.