Push a message to an eSIM
curl --request POST \
--url https://sandbox-api.sakawave.example/v1/esims/{profileId}/messages \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"text": "Your data plan is active. Safe travels."
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({text: 'Your data plan is active. Safe travels.'})
};
fetch('https://sandbox-api.sakawave.example/v1/esims/{profileId}/messages', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://sandbox-api.sakawave.example/v1/esims/{profileId}/messages"
payload = { "text": "Your data plan is active. Safe travels." }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"id": "01K2Z3AB4M5N6P7Q8RSTVWXYZA",
"profileId": "01K2Z3AB4R5S6T7V8WXYZABCDE",
"body": "Your data plan is active. Safe travels.",
"status": "sent",
"failureReason": null,
"createdAt": "2026-08-29T14:05:00.000Z"
}{
"statusCode": 400,
"message": "Must be a valid identifier.",
"code": "validation_failed",
"errors": [
{
"message": "Must be a valid identifier.",
"field": "accountId",
"code": "custom",
"path": [
"accountId"
]
}
]
}{
"statusCode": 401,
"code": "INVALID_API_KEY",
"message": "Invalid or inactive API credentials."
}{
"statusCode": 404,
"code": "resource_not_found",
"message": "Resource not found."
}{
"statusCode": 409,
"code": "resource_conflict",
"message": "The request conflicts with the current resource state."
}{
"statusCode": 429,
"message": "Too many API requests. Try again later.",
"code": "api_key_rate_limit_exceeded",
"retryAfterSeconds": 17
}{
"statusCode": 500,
"code": "internal_server_error",
"message": "An unexpected error occurred."
}eSIM
Push a message to an eSIM
Pushes a short message to the device holding the eSIM. One-way: the eSIM carries no phone number, so the recipient cannot reply and nothing reports back that the message arrived.
POST
/
v1
/
esims
/
{profileId}
/
messages
Push a message to an eSIM
curl --request POST \
--url https://sandbox-api.sakawave.example/v1/esims/{profileId}/messages \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"text": "Your data plan is active. Safe travels."
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({text: 'Your data plan is active. Safe travels.'})
};
fetch('https://sandbox-api.sakawave.example/v1/esims/{profileId}/messages', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://sandbox-api.sakawave.example/v1/esims/{profileId}/messages"
payload = { "text": "Your data plan is active. Safe travels." }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"id": "01K2Z3AB4M5N6P7Q8RSTVWXYZA",
"profileId": "01K2Z3AB4R5S6T7V8WXYZABCDE",
"body": "Your data plan is active. Safe travels.",
"status": "sent",
"failureReason": null,
"createdAt": "2026-08-29T14:05:00.000Z"
}{
"statusCode": 400,
"message": "Must be a valid identifier.",
"code": "validation_failed",
"errors": [
{
"message": "Must be a valid identifier.",
"field": "accountId",
"code": "custom",
"path": [
"accountId"
]
}
]
}{
"statusCode": 401,
"code": "INVALID_API_KEY",
"message": "Invalid or inactive API credentials."
}{
"statusCode": 404,
"code": "resource_not_found",
"message": "Resource not found."
}{
"statusCode": 409,
"code": "resource_conflict",
"message": "The request conflicts with the current resource state."
}{
"statusCode": 429,
"message": "Too many API requests. Try again later.",
"code": "api_key_rate_limit_exceeded",
"retryAfterSeconds": 17
}{
"statusCode": 500,
"code": "internal_server_error",
"message": "An unexpected error occurred."
}202 means the provider accepted the message, not that it was delivered — an eSIM that was never installed swallows it silently.
Capped at ten an hour per eSIM, counted across every caller: it reaches a real handset whose holder cannot block or unsubscribe.
Error codes
| Status | code | Cause |
|---|---|---|
409 | esim_profile_not_ready | The eSIM has not been issued yet. |
409 | esim_message_rate_limited | This eSIM has had ten messages in the past hour. |
401 | INVALID_API_KEY | The key is missing, invalid, inactive, expired, from the other environment, or blocked by its IP allowlist. |
429 | api_key_rate_limit_exceeded | The per-minute limit for this key was exceeded. |
503 | esim_feature_disabled | eSIM is not enabled on this deployment. |
503 | esim_catalog_unavailable | The catalog is empty and could not be refreshed from the provider. |
503 | esim_provider_unavailable | The eSIM provider could not be reached. Nothing was charged. |
Authorizations
A secret API key, sent as Authorization: Bearer sk_test_… in sandbox or Bearer sk_live_… in live.
Path Parameters
eSIM ULID. A 26-character ULID.
Required string length:
26Pattern:
^[0-7][0-9A-HJKMNP-TV-Z]{25}$Example:
"01K2Z3AB4C5D6E7F8G9HJKMNPQ"
Body
application/json
Required string length:
1 - 160Response
Successful response.
A 26-character ULID.
Required string length:
26Pattern:
^[0-7][0-9A-HJKMNP-TV-Z]{25}$Example:
"01K2Z3AB4C5D6E7F8G9HJKMNPQ"
A 26-character ULID.
Required string length:
26Pattern:
^[0-7][0-9A-HJKMNP-TV-Z]{25}$Example:
"01K2Z3AB4C5D6E7F8G9HJKMNPQ"
What was sent, at most 160 characters.
sent means the provider accepted it, not that the handset received it.
Available options:
sent, failed The provider's rejection, on a failed attempt.