Skip to main content

RCS Wallet & Billing

RCS messages on SendSeven are paid from a prepaid RCS wallet. The wallet belongs to your billing account, so every workspace on that billing account sends from the same balance. It is separate from your plan's included message pool and from the prepaid SMS balance.

On conversational and non-conversational agents, each RCS message also counts as a SendSeven message on your plan, like a message on any other channel: it uses your included message pool first and is then billed at your plan's message price on the monthly invoice. On newsletter agents there is no SendSeven message fee: the monthly price per recipient from the wallet is the only charge (see Newsletter agents: one price per recipient per month).

This guide explains how the wallet works and documents the wallet endpoints, the campaign cost estimate, and all RCS billing error codes.

RCS is in beta

RCS is available to accounts whose billing country is Germany (DE), or that SendSeven has granted an exception. For an account that is not eligible, the read endpoints keep working, while top-ups, the bank transfer details and turning on automatic top-up answer 403 rcs_not_available. See What eligibility gates for the full list, including agent requests and campaigns.

How the wallet works​

Top-ups​

You add money to the wallet with a top-up:

RuleValue
First top-upAt least 100 EUR net. It activates the wallet.
Later top-upsAt least 50 EUR net each
Maximum per top-up50,000 EUR net
FormatPlain decimal, at most 2 decimal places, e.g. 150 or 150.50
Payment methodscard (credited once the payment succeeds) or bank_transfer (credited when the transfer arrives)
VATAmounts are net. VAT is added where it applies and shown on the invoice you receive for each top-up.

A bank transfer credits the full amount received, including any overpayment. Unused balance is refundable (see Refunds and account closure).

Reservations and charges on delivery​

Sending an RCS message happens in two steps:

  1. Reserve. When the message is sent, the expected charge is reserved from the wallet. available = balance − reserved. If available does not cover the message, the send is refused with insufficient_rcs_balance.
  2. Charge or release. You are charged only when the carrier confirms the message as delivered. The final charge replaces the reservation. If the message expires undelivered, it is free and the reservation is released.

Messages from your contacts to you are always free.

Charge types​

Every delivered message is charged in one of four ways. The in-app How charges work tab of the RCS wallet explains them too.

UnitWhen it applies
basicA plain text message of up to 160 characters, with no suggested replies or actions (the limit is rcs.basic_max_len in the pricing overview)
singleAny other message: longer text, media, rich cards, carousels, or any message with suggestions. A rich card counts as one message.
sessionA conversation. When a recipient replies, the exchange becomes a session that is charged once; further messages in it are free while it lasts. The message they replied to is upgraded to a session (you pay the difference, never twice).
mauMonthly active user, for newsletter agents only: one charge per recipient per calendar month (Europe/Berlin), no matter how many messages they receive. It is charged when the first message of the month is delivered to that recipient; every further message to them that month costs nothing.

Which units apply depends on your RCS agent type:

  • Conversational agents use basic, single and session.
  • Non-conversational agents always charge the message unit (basic or single); there are no sessions.
  • Newsletter agents charge mau. They send campaigns and platform confirmation messages only (opt-in, double opt-in and STOP confirmations are free); free-text, bot, flow and AI messages are refused. Carriers limit how many newsletters one recipient may receive per day and per month (currently 2 per day and 30 per month). Messages sent by a newsletter agent carry no SendSeven message fee and do not use your included message pool.

Your net unit prices are in your RCS offer and are returned by GET /billing/rcs-wallet/prices. Billing months follow the Europe/Berlin calendar month.

Newsletter agents: one price per recipient per month​

A newsletter agent costs one flat price per recipient per calendar month: EUR 0.19 net by default, or the mau price in your RCS offer. Every newsletter that recipient receives in that month is included, up to the carrier limit of 2 newsletters per day and 30 per month. Up to 3 messages sent to the same recipient within 60 seconds count as one newsletter towards this limit. There is no price per message, and no SendSeven message fee is added on top. Opt-in, double opt-in and unsubscribe confirmations are free and do not start the monthly charge.

Welcome offer: for a limited time (the closing date is welcome_offer.cutoff in the pricing overview and is shown in the app), a billing account that submits its first RCS agent request gets EUR 0.19 net per recipient per month as a flat rate for 12 months minimum, with no additional SendSeven message fees. The pricing overview reports the offer as open, locked (secured for your account) or closed.

How this compares with per-message pricing and WhatsApp. The examples use the default prices and the SendSeven message fee of the Basic and Professional plans (EUR 0.02 per message), for newsletters sent as one message each. WhatsApp uses Meta's list price for a marketing message in Germany (EUR 0.1131, billed by Meta) plus the same SendSeven message fee. All net; your offer and plan may differ.

Newsletters to one recipient in a monthsingle (EUR 0.079 + EUR 0.02 fee)WhatsApp marketing (EUR 0.1131 + EUR 0.02 fee)Newsletter agent (mau)
1EUR 0.099EUR 0.133EUR 0.19
2EUR 0.198EUR 0.266EUR 0.19
4.33 (weekly)EUR 0.43EUR 0.58EUR 0.19
8EUR 0.79EUR 1.06EUR 0.19
30 (daily)EUR 2.97EUR 3.99EUR 0.19
  • Break-even on Basic and Professional: a newsletter agent is cheaper than WhatsApp from about 1.4 newsletters per recipient per month (0.19 / 0.1331) and cheaper than single from about 1.9 (0.19 / 0.099), so in practice from the 2nd newsletter. On plans with a lower message fee the break-even against single is slightly higher (about 2.0 on Scale, 2.1 on Enterprise).
  • 1,000 recipients, weekly: about EUR 429 (single), EUR 576 (WhatsApp), EUR 190 (newsletter agent) per month. Daily: EUR 2,970, EUR 3,993 and EUR 190.
  • While the included message pool still covers the messages, no extra SendSeven fee is charged for them; without the fee a newsletter agent beats single from the 3rd newsletter and WhatsApp from the 2nd.
  • Per-message pricing counts messages, not newsletters. A newsletter made of 2 messages (for example an image card followed by a text) costs twice as much, so a newsletter agent pays off even sooner.
  • If you send a recipient only one newsletter a month, per-message pricing is cheaper.
  • The in-app calculator uses the values of GET /rcs/agent-requests/pricing-overview; you can build the same comparison from that response.

Balance warnings​

SendSeven emails the billing account's owners and admins and shows an in-app banner when:

WarningConditionCan be turned off
Balance used upavailable is 0 or belowNo
Low balanceavailable is below your threshold. Default threshold: 20% of your last top-up, at least 20 EUR. You can set your own.Yes (low_warn_enabled)
ForecastAt your average daily spend over the last 7 days, the balance lasts less than 3 daysYes (forecast_warn_enabled)

Each warning is sent at most once per day. Low-balance and forecast warnings are skipped while automatic top-up is on.

Automatic top-up​

With automatic top-up, a saved card is charged for a fixed amount whenever available drops below your threshold:

  • Card only. The top-up amount follows the same minimum and maximum as a manual top-up; the threshold is at least 1 EUR.
  • At most 3 attempts per day. A monthly cap may apply (shown as monthly_cap on the wallet).
  • After 2 consecutive failed payments, automatic top-up turns itself off and the owners and admins are notified by email and in the app. Update the card and turn it on again.

When the balance runs out​

  • Direct sends (API, inbox, flows, bots) are refused with insufficient_rcs_balance. With an API token, POST /messages may answer 402 right away; otherwise the message is created and then fails with the code in meta.error_code (see Where RCS errors appear).
  • Campaigns are not failed. The campaign moves to status paused with throttle_reason insufficient_rcs_balance (or rcs_wallet_blocked), and the recipients not reached yet stay pending. After a top-up the campaign continues automatically. You can also resume it with POST /campaigns/{campaign_id}/resume.

Wallet status​

statusMeaning
activeNormal operation
blocked_negativeThe balance is below zero (for example after a card payment was disputed). RCS sending is refused with rcs_wallet_blocked until a top-up brings the balance back to 0 or more.
frozenSending and top-ups are on hold, for example while the account is being closed or during a payment dispute. Contact support.

Refunds and account closure​

  • Unused balance is refundable on request. Contact [email protected]. Card top-ups are refunded to the card, bank transfer top-ups by bank transfer, oldest top-up first, and a credit note is issued. If the first top-up is refunded in full, the next top-up needs the 100 EUR minimum again.
  • If your RCS request is cancelled, the first top-up is refunded in full.
  • When you close your billing account, the wallet is frozen and settled once all open messages are final. The remaining balance is first offset against your final monthly invoice; anything left over is refunded after support confirms the amount.
  • Deleting a single workspace does not refund anything: the balance belongs to the billing account.

Required scopes and access​

OperationRequirement
Read wallet, prices, ledger, statements, usage, top-up historybilling:read, and either the owner or admin role on the billing account or the account:billing_read scope. API tokens may read.
Bank transfer detailsSame as reading the wallet, plus an eligible account (403 rcs_not_available)
Top up, set up automatic top-up, change warning settingsbilling:update, the owner or admin role on the billing account, and a signed-in user. API tokens, OAuth apps and embedded sessions are refused (403 rcs_interactive_user_required). Top-ups, the setup intent and turning automatic top-up on also need an eligible account (403 rcs_not_available). Top-ups are normally made in the app.
Campaign cost estimatecampaigns:read

The billing account is always the one of the workspace you authenticate against; you never pass it in a request.

Endpoints​

All endpoints are under https://api.sendseven.com/api/v1. Money is always a decimal string in EUR, net. Wallet and ledger amounts keep up to 6 decimal places. Errors use the shape {"detail": {"code": "...", "message": "..."}}, except request-validation errors (see HTTP status codes).

MethodPathPurpose
GET/billing/rcs-walletBalance, status, auto top-up, warning settings, forecast
GET/billing/rcs-wallet/pricesYour net RCS unit prices
GET/billing/rcs-wallet/ledgerWallet transactions (paginated)
GET/billing/rcs-wallet/usageCharges of a month by workspace, agent and type
GET/billing/rcs-wallet/statements/{month}Monthly statement
GET/billing/rcs-wallet/statements/{month}.csvMonthly statement as CSV
GET/billing/rcs-wallet/topupsTop-up history (paginated)
POST/billing/rcs-wallet/topupsStart a top-up
GET/billing/rcs-wallet/bank-transferBank transfer details and your payment reference
POST/billing/rcs-wallet/auto-topup/setup-intentPrepare saving a card for automatic top-up
PUT/billing/rcs-wallet/auto-topupTurn automatic top-up on or off
PUT/billing/rcs-wallet/warningsChange balance warning settings
GET/campaigns/{campaign_id}/rcs-estimateWhat the RCS part of a campaign will reserve

Get the wallet​

curl "https://api.sendseven.com/api/v1/billing/rcs-wallet" \
-H "Authorization: Bearer s7_api_a1b2c3d4e5f6789012345678abcdef00"
{
"billing_account_id": "ba_123",
"exists": true,
"currency": "EUR",
"balance": "412.380000",
"reserved": "12.500000",
"available": "399.880000",
"status": "active",
"writes_enabled": true,
"enforcement_enabled": true,
"first_topup_at": "2026-09-01T09:12:44Z",
"last_topup_amount": "500.00",
"minimum_topup": "50",
"auto_topup": {
"enabled": true,
"threshold": "100.00",
"amount": "250.00",
"monthly_cap": null,
"has_payment_method": true,
"fail_count": 0,
"disabled_at": null
},
"warnings": {
"low_warn_enabled": true,
"forecast_warn_enabled": true,
"low_warn_threshold": null,
"effective_low_threshold": "100.00"
},
"forecast": {
"avg_daily_charge": "18.420000",
"days_left": "21.7"
},
"banner": null,
"role": "owner",
"can_manage": true
}
FieldDescription
existsfalse until the first top-up is credited. The other fields then show defaults.
balance / reserved / availableavailable = balance − reserved; sends are checked against available
statusactive, blocked_negative or frozen (see Wallet status)
writes_enabledWhether top-ups and settings changes are possible for this billing account right now
enforcement_enabledWhether RCS sends are checked against the balance
minimum_topup100 before the first top-up, 50 afterwards
auto_topupAutomatic top-up settings; fail_count counts consecutive failed attempts, disabled_at is set when it turned itself off
warnings.effective_low_thresholdThe threshold actually used: your own, else 20% of the last top-up with a 20 EUR floor
forecast.days_leftavailable ÷ avg_daily_charge (7-day average); null without recent usage
bannerThe in-app banner currently shown: exhausted, blocked, frozen, auto_topup_failed, low, forecast or null
role / can_manageYour role on the billing account; can_manage is true for owners and admins

Get prices​

curl "https://api.sendseven.com/api/v1/billing/rcs-wallet/prices" \
-H "Authorization: Bearer s7_api_a1b2c3d4e5f6789012345678abcdef00"
{
"currency": "EUR",
"prices_are_net": true,
"price_source": "plan",
"prices": {
"basic": "<net EUR>",
"single": "<net EUR>",
"session": "<net EUR>",
"mau": "<net EUR>"
},
"session_upgrade": {
"from_basic": "<net EUR>",
"from_single": "<net EUR>"
},
"agent_fee": {
"enabled": false,
"amount": "<net EUR>",
"grace_months": 6,
"min_monthly_revenue": "<net EUR>"
}
}

The prices are resolved exactly as a real send would be. Unit prices are decimal strings with 2 to 6 decimal places.

FieldDescription
price_sourceWhere the prices come from, most specific first: tenant_override (this workspace), ba_override (this billing account), plan, platform_default, code_default
pricesNet price per basic, single, session and mau unit
session_upgradeThe extra charge when a reply turns an already charged basic or single message into a session (session price minus the unit already paid, never negative)
agent_feeA monthly fee for your RCS agent, if your offer includes one. When enabled is false no agent fee is charged. Otherwise it is not charged during the first grace_months after launch, nor in a month where your RCS charges reach min_monthly_revenue.

Returns 503 rcs_prices_unavailable if the prices cannot be loaded right now; retry later.

List ledger entries​

GET /billing/rcs-wallet/ledger?page=1&page_size=50

Query parameterDescription
page, page_sizePagination (page_size 1 to 200, default 50)
typeComma-separated ledger types, e.g. CHARGE_SINGLE,CHARGE_SESSION
tenant_idOnly entries of one workspace of this billing account
monthyyyy-mm (Europe/Berlin billing month)

Ledger types:

TypeMeaning
TOPUP / TOPUP_AUTOManual / automatic top-up credited
TOPUP_REFUNDRefund of unused balance
CHARGE_BASIC, CHARGE_SINGLE, CHARGE_SESSION, CHARGE_MAUCharge for a delivered message
CHARGE_SESSION_UPGRADEA reply upgraded a charged message to a session
AGENT_FEEMonthly agent fee
ADJUSTMENTCorrection made by SendSeven support
CHARGEBACKA disputed payment was taken back

Charges have a negative amount. A reversed charge appears as a positive entry of the same type.

{
"items": [
{
"id": "0192f1c4-7a1e-7c3b-9d2a-5b6c7d8e9f01",
"created_at": "2026-09-21T14:03:12Z",
"type": "CHARGE_SINGLE",
"amount": "-<net EUR>",
"reserved_delta": "-<net EUR>",
"balance_after": "412.380000",
"billing_month": 202609,
"tenant_id": "tenant_abc123",
"channel_id": "ch_rcs_001",
"rbm_message_id": "b3f0c2d4-1e2f-4a5b-8c7d-9e0f1a2b3c4d",
"topup_id": null,
"unit": "single",
"unit_price": "<net EUR>",
"carrier_event_at": "2026-09-21T14:03:10Z"
}
],
"pagination": { "total": 1, "page": 1, "page_size": 50, "total_pages": 1, "has_next": false, "has_prev": false }
}

Monthly usage​

GET /billing/rcs-wallet/usage?month=2026-09 returns the charges of one month (default: the current Europe/Berlin month) grouped by workspace, RCS agent (channel) and ledger type:

{
"billing_account_id": "ba_123",
"month": "2026-09",
"billing_month": 202609,
"currency": "EUR",
"total_charged": "187.620000",
"items": [
{
"tenant_id": "tenant_abc123",
"tenant_name": "Main workspace",
"channel_id": "ch_rcs_001",
"channel_name": "Shop RCS",
"type": "CHARGE_SINGLE",
"count": 1520,
"charged": "152.000000"
}
]
}

Statements and CSV export​

GET /billing/rcs-wallet/statements/{month} with month as yyyy-mm:

{
"billing_account_id": "ba_123",
"month": "2026-09",
"billing_month": 202609,
"currency": "EUR",
"opening_balance": "100.000000",
"closing_balance": "412.380000",
"totals": {
"topups": "500.000000",
"charges": "187.620000",
"agent_fees": "0",
"refunds": "0",
"chargebacks": "0",
"adjustments": "0",
"net_change": "312.380000"
},
"by_type": {
"TOPUP": { "count": 1, "amount": "500.000000" },
"CHARGE_SINGLE": { "count": 1520, "amount": "-152.000000" }
},
"by_workspace": [
{ "tenant_id": "tenant_abc123", "tenant_name": "Main workspace", "charged": "187.620000", "count": 1874 }
],
"generated_at": "2026-09-27T08:00:00Z",
"is_final": false
}

In totals, money going out (charges, agent_fees, refunds, chargebacks) is a positive number; adjustments and net_change keep their sign. is_final is false while the month is still running.

GET /billing/rcs-wallet/statements/{month}.csv downloads the month's ledger as rcs-statement-yyyy-mm.csv with these columns:

created_at, billing_month, type, amount_eur, balance_after_eur, workspace_id, workspace_name, channel_id, unit, unit_price_eur, rbm_message_id, topup_id, carrier_event_at, entry_id

An invalid month returns 422 rcs_invalid_month.

Top-ups​

List: GET /billing/rcs-wallet/topups?page=1&page_size=20 (page_size up to 100), newest first:

{
"items": [
{
"id": "0192f1c4-0000-7000-8000-000000000001",
"method": "bank_transfer",
"status": "credited",
"amount_net": "500.00",
"vat_amount": "95.00",
"amount_gross": "595.00",
"vat_rate": "0.19",
"requested_net": "500.00",
"received_total_gross": "595.00",
"refunded_net": null,
"reference": "RCS-4F2A9C1B7D",
"failure_code": null,
"credited_at": "2026-09-03T10:21:05Z",
"created_at": "2026-09-01T09:12:44Z"
}
],
"pagination": { "total": 1, "page": 1, "page_size": 20, "total_pages": 1, "has_next": false, "has_prev": false }
}

Top-up status values: pending, requires_action (card needs 3-D Secure), awaiting_funds (bank transfer not received yet), processing, credited, failed, canceled, refunded, partially_refunded.

Create (signed-in owner or admin; this is what the app does):

curl -X POST "https://api.sendseven.com/api/v1/billing/rcs-wallet/topups" \
-H "Authorization: Bearer <user session token>" \
-H "Content-Type: application/json" \
-d '{ "amount": "250.00", "method": "card" }'
FieldRequiredDescription
amountYesNet EUR (see Top-ups)
methodYescard or bank_transfer
payment_method_idNoA saved card to charge; the billing account's default card otherwise

Response 201:

{
"topup_id": "0192f1c4-0000-7000-8000-000000000002",
"status": "requires_action",
"amount": "250.00",
"method": "card",
"client_secret": "<payment confirmation secret>",
"requires_action": true,
"hosted_invoice_url": null,
"bank_transfer_instructions": null,
"failure_code": null
}
  • Card: check status. credited means the balance is already available. requires_action means the card needs 3-D Secure confirmation, which the app completes with client_secret. A declined card returns 201 with status failed and a failure_code; nothing is credited.
  • failure_code is set only when status is failed, otherwise null. It is always one of these short codes, never a raw message from the card issuer: card_declined, insufficient_funds, expired_card, incorrect_cvc, incorrect_number, processing_error, authentication_required, card_not_supported, currency_not_supported, try_again_later, canceled, payment_failed (anything else). Treat unknown values like payment_failed, since the list can grow. The same codes appear in failure_code of the top-up history.
  • Bank transfer: nothing is created yet. The response has topup_id null, status awaiting_funds, and bank_transfer_instructions with the same content as GET /billing/rcs-wallet/bank-transfer. Always include the reference in the transfer. Once SendSeven has received the money, the top-up appears in the history as credited and its invoice is issued.
  • Repeating the same card top-up (same amount) within 60 seconds returns the top-up already in progress instead of charging twice.

Bank transfer details​

GET /billing/rcs-wallet/bank-transfer?amount=250.00 is read-only: it creates no top-up and sends no email. amount (net EUR) is optional; with it, the response also contains the VAT and the gross amount to transfer.

FieldDescription
account_holder, iban, iban_formatted, bic, bank_nameSendSeven's bank account to transfer to. The values are shown in the app; they are not published here.
intermediary_bicOnly needed for transfers from outside the SEPA area; may be null
referenceYour payment reference. It is fixed for your billing account (RCS- followed by 10 characters), so every bank top-up uses the same one.
currency, vat_rate, vat_schemeCurrency (eur), the VAT rate that applies to your account and how it is applied
min_amount_net, min_amount_gross, max_amount_netThe minimum (100 EUR net for the first top-up, then 50) and the maximum per top-up
amount_net, vat_amount, amount_grossFor the amount you passed: net, VAT and what to transfer. null without amount.
note_codecredit_after_receipt: the wallet is credited once the transfer has been received

The wallet is credited with the net amount of what was received, including any overpayment. Errors: 403 rcs_not_available (account not eligible), 422 rcs_method_disabled (bank transfer not available for this account), 422 rcs_first_topup_min / rcs_min_amount for an amount below the minimum, 503 rcs_bank_details_unavailable (details not available right now).

Automatic top-up​

  1. POST /billing/rcs-wallet/auto-topup/setup-intent returns {"client_secret": "..."}, used by the app to save a card for off-session payments.
  2. PUT /billing/rcs-wallet/auto-topup:
{ "enabled": true, "threshold": "100.00", "amount": "250.00" }
FieldDescription
enabledTurn automatic top-up on or off
thresholdTop up when available drops below this (at least 1 EUR). Required when enabling.
amountNet amount per automatic top-up. Required when enabling.
payment_method_idOptional saved card; a card on file is required to enable

Enabling without threshold or amount returns 422 rcs_auto_topup_incomplete. Enabling resets fail_count.

Warning settings​

PUT /billing/rcs-wallet/warnings is a partial update; omit a field to leave it unchanged. Send "low_warn_threshold": null to go back to the default rule. Returns the refreshed wallet.

{ "low_warn_enabled": true, "low_warn_threshold": "150.00", "forecast_warn_enabled": false }

The wallet is created with the first top-up; before that this endpoint returns 404 rcs_wallet_not_found.

Campaign cost estimate​

GET /campaigns/{campaign_id}/rcs-estimate (scope campaigns:read) shows what the RCS part of a campaign will reserve from the wallet, so you can top up before sending:

curl "https://api.sendseven.com/api/v1/campaigns/camp_123/rcs-estimate" \
-H "Authorization: Bearer s7_api_a1b2c3d4e5f6789012345678abcdef00"
{
"campaign_id": "camp_123",
"currency": "EUR",
"recipients": 5000,
"reachable": 4600,
"billable_recipients": 4600,
"amount": "<net EUR>",
"wallet_available": "399.880000",
"wallet_status": "active",
"shortfall": "<net EUR>",
"sufficient": false,
"billing_active": true,
"enforced": true,
"price_source": "plan",
"recipient_source": "audience",
"channels": [
{
"channel_id": "ch_rcs_001",
"agent_type": "conversational",
"recipients": 5000,
"reachable": 4200,
"unreachable": 400,
"unknown": 400,
"already_mau": 0,
"billable_recipients": 4600,
"units": ["single"],
"per_recipient": "<net EUR>",
"amount": "<net EUR>",
"mau_periods": [],
"reachability_available": true
}
]
}
FieldDescription
amountReachable RCS recipients × the price per recipient, summed over all RCS channels of the campaign
sufficient / shortfallsufficient is false when the wallet does not cover amount (or the wallet is not active); shortfall is the missing amount
wallet_available / wallet_statusThe current wallet; null when no balance is reserved for this account
billing_active / enforcedWhether the wallet is reserved from for this account and whether sends are checked against it
recipient_sourceaudience (planned from the campaign's lists) or campaign_messages (a campaign already sending: only recipients not sent yet are counted)
channels[].reachable / unreachable / unknownRecipients last seen as reachable on RCS, not reachable (left out of the estimate), or not checked yet (counted)
channels[].unitsThe units each recipient's message is expected to use, e.g. ["single"]
channels[].already_mauNewsletter agents: recipients already charged as a monthly active user in the month(s) in mau_periods; they are not charged again

For newsletter agents, amount is the whole cost of the campaign: there is no SendSeven message fee. The plan cost estimate (GET /campaigns/{campaign_id}/estimate-cost) therefore leaves recipients on a newsletter agent out of total_cost_eur, breakdown and the included-pool figures, and lists them in rcs_newsletter (recipient_count, sendseven_fee_eur: 0). recipient_count still includes them.

The estimate is informational. A campaign is never refused up front: if the balance runs out while sending, it pauses and continues after a top-up (see When the balance runs out).

RCS agent requests​

Before a workspace can send RCS, it needs its own RCS agent: the verified sender (name, logo, colours) that recipients see. You apply for it with an agent request. The SendSeven team submits the request to Google and the mobile carriers for verification once two things are in place:

  1. The request is complete and submitted.
  2. The billing account has a credited first RCS top-up of at least 100 EUR net (see Top-ups).

If you submit before the top-up is credited, the request waits in awaiting_topup and moves on to submitted by itself as soon as the top-up is credited. Most customers fill in the form on the RCS request page in the app, which keeps the request as a draft you can edit and save until you submit it. A draft costs nothing: money only moves with a top-up. These endpoints do the same; the app also uses the pricing overview and prefill endpoints below.

Access​

OperationRequirement
List and get requests, pricing overview, prefillchannels:read. API tokens may read. OAuth apps and embedded sessions are refused (403 rcs_request_forbidden). Not eligibility-gated.
Create, edit, upload files, submitchannels:create, a signed-in user (API tokens get 403 rcs_interactive_user_required) and an eligible account: billing country DE or an exception granted by SendSeven (403 rcs_not_available).
Cancelchannels:create and a signed-in user; always allowed, also for accounts that are not eligible.

Requests belong to the workspace you authenticate against; the billing account is derived from it and never passed in a request.

Endpoints​

MethodPathPurpose
GET/rcs/agent-requestsList this workspace's requests, newest first (page, page_size up to 100, optional status as a comma-separated list)
POST/rcs/agent-requestsCreate a draft (201); every field is optional while in draft
GET/rcs/agent-requests/pricing-overviewCurrent prices, SendSeven fees, welcome offer and WhatsApp reference for the request page
GET/rcs/agent-requests/prefillSuggested form values from your account (never writes)
GET/rcs/agent-requests/{request_id}Get one request
PATCH/rcs/agent-requests/{request_id}Edit a request in draft, awaiting_topup or changes_requested. Only the fields you send change; null clears a field; nested objects (brand_contact, newsletter) are replaced as a whole.
POST/rcs/agent-requests/{request_id}/assets/{kind}Upload a file as multipart field file. kind is logo, banner or registry_pdf. A new upload replaces the earlier one.
POST/rcs/agent-requests/{request_id}/submitSubmit for review: becomes submitted, or awaiting_topup until the first top-up is credited
POST/rcs/agent-requests/{request_id}/cancelWithdraw a request in draft, awaiting_topup or changes_requested. Returns {"success": true, "id": "...", "status": "cancelled"}. Top-ups stay as wallet credit; for a refund, contact support.

Form fields​

FieldRequired to submitNotes
display_nameYes1-40 characters
descriptionYes1-100 characters
brand_colorYes#RRGGBB, with a contrast of at least 4.5:1 against white
agent_typeYesconversational, non_conversational or newsletter
use_caseYespromotional, transactional, otp or multi_use (allowed combinations below)
contact_phoneYesInternational format, for example +4930123456
contact_emailYesShown to recipients
website_url, privacy_policy_url, terms_urlYeshttps:// URLs
brand_contactname and emailPerson at the brand who confirms the registration; also job_title, phone
brand_authorizationYes, trueYou confirm you are authorised to register the agent for this brand
opt_in_descriptionYesHow recipients agree to receive messages (up to 1,000 characters)
triggersYesWhat triggers the agent's messages (up to 1,000 characters)
sample_messagesYes1 to 5 example messages
opt_out_wordingYesHow recipients stop messages (up to 500 characters)
expected_monthly_volumeYesWhole number
newsletterNewsletter agents: name, cadence, management_templatescadence: daily, weekly, biweekly, monthly or irregular; management_templates: up to 10 texts such as the subscribe and unsubscribe confirmations

Files:

kindFormatLimit
logoPNG or JPEG, 224 x 224 px50 KB
bannerPNG or JPEG, 1440 x 448 px200 KB
registry_pdfPDF extract from the commercial register10 MB

Allowed agent_type / use_case combinations:

agent_typeAllowed use_case
conversationalpromotional, transactional, multi_use
non_conversationalpromotional, transactional, otp, multi_use
newsletterpromotional

Unknown fields are rejected.

Response​

{
"id": "0192f1c4-0000-7000-8000-0000000000a1",
"status": "awaiting_topup",
"agent_type": "conversational",
"use_case": "transactional",
"billing_category": "CONVERSATIONAL",
"form": { "display_name": "Acme Support", "brand_color": "#1A73E8" },
"assets": {
"logo": { "content_type": "image/png", "size": 18342, "width": 224, "height": 224, "filename": "logo.png", "uploaded_at": "2026-09-20T08:14:02Z", "url": "https://..." }
},
"carrier_states": { "telekom": { "state": "not_submitted" } },
"missing_fields": [],
"topup_required": true,
"first_topup_minimum_net": "100.00",
"review_note": null,
"channel_id": null,
"google_agent_id": null,
"submitted_at": null,
"launched_at": null,
"cancelled_at": null,
"created_at": "2026-09-20T08:10:11Z",
"updated_at": "2026-09-20T08:20:45Z"
}
  • missing_fields lists what is still needed before you can submit (form paths such as brand_contact.email, and assets.logo); it is empty outside the editable statuses.
  • topup_required is true while the first top-up of at least first_topup_minimum_net is outstanding.
  • review_note carries the review team's note when changes are requested.
  • url of the registry PDF is always null.
  • billing_category is what the agent is registered and priced as: newsletter agents are NON_CONVERSATIONAL.
  • carrier_states[...].state: not_submitted, submitted, in_review, launched, rejected.
  • Once the agent is live, channel_id is the RCS channel you send from.

Request status values:

StatusMeaning
draftBeing filled in
awaiting_topupSubmitted, waiting for the first top-up of at least 100 EUR net; moves on automatically
submittedWith the SendSeven team
in_reviewUnder review by Google and the carriers
changes_requestedUpdate the request as described in review_note, then submit again
brand_verifiedThe brand is verified; carrier approval is pending
launched_partialLive on some carriers
launchedLive
cancelledWithdrawn
offboardedNo longer active

Pricing overview​

GET /rcs/agent-requests/pricing-overview returns everything the request page shows about prices. It works before the wallet exists and for accounts that are not eligible (eligible tells you which). All money values are net EUR decimal strings with 2 to 6 decimal places.

{
"currency": "EUR",
"prices_are_net": true,
"eligible": true,
"rcs": {
"basic": "0.065",
"single": "0.079",
"session": "0.11",
"mau": "0.19",
"session_upgrade": { "from_basic": "0.045", "from_single": "0.031" },
"agent_fee": { "enabled": false, "amount": "100.00", "grace_months": 6, "min_monthly_revenue": "50.00" },
"basic_max_len": 160
},
"welcome_offer": { "state": "open", "mau_price": "0.19", "cutoff": "<ISO 8601 UTC>", "guarantee_months": 12 },
"agent_types": [
{ "type": "newsletter", "billing": "mau", "unit": "mau", "unit_price": "0.19", "sendseven_fee_per_message": "0.00" },
{ "type": "non_conversational", "billing": "per_message", "unit": "single", "unit_price": "0.079", "sendseven_fee_per_message": "0.02" },
{ "type": "conversational", "billing": "per_message", "unit": "session", "unit_price": "0.11", "sendseven_fee_per_message": "0.02" }
],
"sendseven_fee": {
"campaign_message": "0.02",
"message": "0.02",
"included_messages": 2500,
"included_per_billable_channel": false,
"applies_to_rcs_per_message": true
},
"whatsapp_reference": {
"marketing_message_de": "0.1131",
"source": "meta_list_price",
"sendseven_fee_per_message": "0.02",
"as_of": "2026-09"
}
}

The example shows the default list prices on the Professional plan; your response has your own prices and plan fees.

FieldDescription
eligibleWhether this account may request agents, top up and send RCS campaigns
rcsYour unit prices, resolved as for a real send (same values as GET /billing/rcs-wallet/prices), plus basic_max_len, the text length up to which a plain message is basic
welcome_offer.stateopen (you can still get the offer), locked (secured for your billing account) or closed. mau_price and guarantee_months are null when closed. cutoff is the closing date, or null if none is set.
agent_types[]Per agent type: how it is billed, the unit it is priced by, that unit's price, and the SendSeven message fee added per message. Non-conversational sends use the campaign message fee; conversational sends use the conversation message fee. Non-conversational agents also send basic messages; conversational agents start with basic/single and upgrade to session on a reply (see Charge types).
sendseven_feeYour plan's SendSeven fees per campaign message and per conversation message, and the included message pool. included_per_billable_channel is true on plans whose pool grows with each billable channel. applies_to_rcs_per_message is true: per-message RCS sends carry the fee and use the pool. Newsletter agents never do.
whatsapp_referenceFor comparisons: Meta's list price for a WhatsApp marketing message in Germany (billed by Meta, not by SendSeven), your SendSeven fee per campaign message, and the month the Meta price was taken from. null when no reference price is available; hide the WhatsApp comparison then.

Returns 503 rcs_prices_unavailable if the prices cannot be loaded right now.

Prefill suggestions​

GET /rcs/agent-requests/prefill returns what your account already knows, as suggestions for an empty request form. It never writes anything. Only use a suggestion for a field the user has not filled in, and let them confirm it.

{
"suggestions": {
"display_name": "Acme",
"website_url": "https://acme.example",
"contact_email": "[email protected]",
"contact_phone": "+4930123456",
"brand_contact": { "name": "Jane Doe", "email": "[email protected]" }
},
"context": {
"company_legal_name": "Acme GmbH",
"billing_country": "DE",
"billing_city": "Berlin",
"default_language": "de",
"logo_url": "https://..."
}
}
FieldSource
suggestions.display_nameYour company name, else the workspace name. A name longer than 40 characters is skipped, never cut.
suggestions.website_urlThe workspace website, else the billing account website; https:// only (a bare domain gets https://, an http:// address is left out)
suggestions.contact_emailThe signed-in user's email
suggestions.contact_phoneThe workspace company phone, if it is in international format
suggestions.brand_contactThe signed-in user's name and email
context.company_legal_nameThe company's legal name, for reference
context.billing_country / billing_cityFrom the billing address (city falls back to the company city)
context.default_languageThe workspace's default language
context.logo_urlA temporary link to the workspace logo, if there is one. Upload the agent logo separately as assets/logo (224 x 224 px).

Every value can be null, and brand_contact is null when neither name nor email is known. Every non-null suggestion passes the form validation as-is. Returns 503 rcs_prefill_unavailable if the account data cannot be loaded right now.

Agent request errors​

HTTPCodeMeaning
403rcs_request_forbiddenThis credential cannot access agent requests
403rcs_interactive_user_requiredChanges need a signed-in user, not an API token
403rcs_not_availableRCS is not available for this account (billing country is not DE and no exception was granted)
404rcs_billing_account_not_foundThe workspace has no billing account
404rcs_request_not_foundNo such request in this workspace
404rcs_asset_kind_invalidkind must be logo, banner or registry_pdf
409rcs_agent_requests_disabled / rcs_billing_writes_disabledAgent requests are not available for this account yet
409rcs_request_not_editableThe request's status does not allow changes
409rcs_invalid_transitionThe request cannot be submitted or cancelled in its current status. Once it is with the review team, contact support to cancel it.
413rcs_asset_too_largeThe file is above the limit for its kind
415rcs_asset_invalid_typeWrong file type, or the content does not match the file type
422rcs_request_incompleteRequired fields or files are missing; fields in detail lists them
422rcs_d23_use_case_not_alloweduse_case is not allowed for this agent_type; detail names both
422rcs_brand_color_invalid / rcs_brand_color_contrastNot a #RRGGBB colour, or not enough contrast against white
422rcs_asset_empty / rcs_asset_wrong_dimensions / rcs_asset_corruptThe file is empty, has the wrong size in pixels, or cannot be read
422rcs_status_invalidUnknown value in the status filter
503rcs_storage_unavailableThe file could not be stored; try again
503rcs_prices_unavailable / rcs_prefill_unavailableThe pricing overview or prefill could not be loaded; try again

Error codes​

Where RCS errors appear​

  • Synchronous: wallet endpoints and POST /messages return an HTTP error with {"detail": {"code": "...", "message": "..."}}.
  • On the message: when a send is refused or fails after the message was created, the message moves to failed and meta.error_code holds the code (also in the message.failed webhook).
  • On a campaign: a campaign paused for the RCS balance has status paused and throttle_reason set to the code.

Send refusals​

CodeWhereMeaningWhat to do
insufficient_rcs_balance402 on POST /messages (API tokens), meta.error_code, campaign throttle_reasonavailable does not cover the messageTop up; paused campaigns continue automatically
rcs_wallet_blocked402 on POST /messages (API tokens), meta.error_code, campaign throttle_reasonThe wallet is not active (balance below zero, or frozen)Top up to bring the balance to 0 or more; contact support if frozen
rcs_newsletter_free_text_off409 on POST /messages, meta.error_code in flowsNewsletter agents only send campaigns and confirmation messagesSend through a campaign, or use a conversational agent
rcs_newsletter_limit_reachedmeta.error_code (campaign recipient fails)The recipient already received the carrier's maximum number of newsletters for the day or monthNot retried for this recipient; send later
rcs_newsletter_stop_confirm_offmeta.error_codeA STOP confirmation was requested on a newsletter agent, where carriers do not allow itNone; the opt-out itself is still honoured
rcs_not_reachablemeta.error_codeThe recipient's device or network does not support RCS for your agentUse another channel for this contact. There is no automatic fallback to SMS.
rcs_ttl_expiredmeta.error_codeThe message was not delivered before it expired and was withdrawn. Not charged.Send again if still relevant
rcs_ttl_revoke_failedmeta.error_codeThe message expired but could not be withdrawn. If it is delivered later anyway, it is charged and its status becomes delivered.None
rcs_billing_unavailablemeta.error_codeThe balance could not be checked for a momentRetried automatically
rcs_billing_writes_disabledmeta.error_codeRCS billing is not enabled for this billing account yetContact support
rcs_missing_deterministic_idmeta.error_codeInternal consistency check refused the sendContact support with the message id
rcs_send_already_startedmeta.error_codeA duplicate attempt of a send that is already in progress was stopped, so the recipient is not charged twiceNone
rcs_lease_exhaustedcampaigns (not shown on messages)A campaign's pre-reserved balance was used up; the send is retried once directly against the walletNone

Campaign pause reasons​

throttle_reasonMeaningResumes
insufficient_rcs_balanceThe wallet cannot fund the next RCS recipientsAutomatically after a top-up, or with POST /campaigns/{campaign_id}/resume
rcs_wallet_blockedThe wallet is not activeAutomatically once the wallet is active and covers the next send again
rcs_not_availableA campaign scheduled on RCS reached its send time while the account is not eligible for RCS. Nothing was sent.Never automatically. Remove RCS from the campaign's targeting (PUT /campaigns/{campaign_id}), then POST /campaigns/{campaign_id}/resume

The recipients not reached yet stay pending and are not marked failed. A campaign resumes automatically only when the wallet is active and covers the next batch of sends.

Wallet API errors​

HTTPCodeMeaning
403rcs_billing_forbiddenThis credential or user may not access the wallet (needs owner/admin or account:billing_read; writes need owner/admin)
403rcs_interactive_user_requiredTop-ups and settings changes need a signed-in user, not an API token
403rcs_not_availableRCS is not available for this account: top-ups, bank transfer details and turning on automatic top-up are refused
404rcs_billing_account_not_foundThe workspace has no billing account
404rcs_workspace_not_foundThe tenant_id filter is not a workspace of this billing account
404rcs_wallet_not_foundThe wallet is created with the first top-up
409rcs_billing_writes_disabled / rcs_writes_disabledTop-ups or settings changes are not available for this account right now
409rcs_no_billing_customerThe billing account has no payment profile yet; add a payment method in billing settings first
409rcs_wallet_blockedThe wallet is frozen or the billing account is scheduled for deletion; no top-ups or automatic top-up changes
422rcs_first_topup_minThe first top-up must be at least 100 EUR net
422rcs_min_amountA top-up must be at least 50 EUR net
422rcs_method_disabledBank transfer top-ups are not available for this account
422rcs_no_payment_methodNo usable card on file (card top-up or automatic top-up)
422rcs_invalid_amountAmount not a positive EUR amount in whole cents or above 50,000; for automatic top-up also a missing amount, a threshold below 1 EUR, or an amount above the monthly cap
422rcs_invalid_methodmethod must be card or bank_transfer
422rcs_invalid_monthmonth must be yyyy-mm
422rcs_invalid_ledger_typeUnknown ledger type filter
422rcs_auto_topup_incompletethreshold and amount are required to enable automatic top-up
422rcs_invalid_warning_settingslow_warn_enabled / forecast_warn_enabled must be true or false
500rcs_topup_failed, rcs_setup_intent_failed, rcs_auto_topup_failed, rcs_bank_details_failedUnexpected error; nothing was charged twice, retry later
502rcs_stripe_errorThe payment provider could not start the payment
503rcs_prices_unavailablePrices cannot be loaded right now
503rcs_topups_unavailableTop-ups are temporarily unavailable
503rcs_bank_details_unavailableThe bank transfer details are not available right now

HTTP status codes​

StatusMeaning for RCS
402 Payment RequiredThe RCS balance does not cover the message (insufficient_rcs_balance) or the wallet is not active (rcs_wallet_blocked). Top up and retry.
409 ConflictThe request conflicts with the current state: a newsletter agent refusing free text, a frozen wallet, or billing changes not available for the account. Retrying without a change does not help.
422 Unprocessable EntityThe request is invalid. Codes starting with rcs_ use the {"detail": {"code", "message"}} shape; malformed bodies (for example an amount with 3 decimals or an unknown field) return the standard validation shape {"detail": [{"loc": [...], "msg": "...", "type": "..."}]}.
503 Service UnavailableTemporary; retry later with backoff

Next Steps​