Outbound policies
An outbound policy is a named set of rules for calls your PBX places to the phone network. It says which countries and number prefixes may be called, how many calls may run, how much may be spent in a day, and whether calls are recorded. You write a policy once and attach it to as many trunks as you like. A policy is live as soon as you create it, and every change you save reaches every attached trunk within a minute.
A trunk with no policy refuses every outbound call.
Policy IDs start with pol_, for example pol_01992f3b-0a27-7f13-8c4e-3b9d6a1e5f20.
What a policy controls
You create a policy with POST /v1/outbound-policies and replace its settings with
PATCH /v1/outbound-policies/{policy_id}. Both take the same body, and every field is required:
Code
| Field | Meaning |
|---|---|
name | Lowercase letters, digits and hyphens, up to 63 characters. Unique in your organization. |
concurrency | Most calls active at once across every trunk using the policy, counting inbound and outbound calls, or null for no policy-level cap. |
cps | Most new outbound calls per second, or null. Inbound calls are not refused for CPS. |
max_call_duration_seconds | Longest call allowed, or null. |
max_destination_rate_minor | Highest per-unit rate a destination may cost, as an integer of minor units (kobo for NGN), or null. |
daily_spend_limit_minor | Most that calls under the policy may spend in a day, as an integer of minor units, or null. |
recording_mode | off or all. |
recording_channels | Always 2: each party on its own channel. |
recording_retention_days | 30, 90 or 365. |
A policy's currency is always NGN. Money is an integer of minor units, so 5000000 is ₦50,000.00.
Read it as an exact integer, not a floating-point number, to avoid rounding.
Signals checks policy limits together with the limits on the trunk, the subaccount and your
organization. A call must fit within all of them. The policy's ceilings object reports the saved
value of each limit. ceilings.daily_spend also shows used_today_minor and resets_at.
Recording
Setting recording_mode to all records every outbound call under the policy. Recording needs both
of the following:
- Your organization has accepted the recording terms in the console. Without that, the request
fails with
409 recording_consent_required. - Your project's price book prices recording.
The policy's recording.applied field tells you whether recording is in effect.
Destination rules
Destination rules decide which numbers your PBX may call. Each rule allows or denies one country or one prefix:
- A country rule names an ISO 3166-1 alpha-2 code, such as
NGorGH. It matches that country's calling code. Countries that share a calling code, such as the United States and Canada on+1, have no code of their own, so use prefix rules for them. - A prefix rule names the leading E.164 digits without the
+, such as233for Ghana or2348091for a range of Nigerian mobile numbers. A prefix is 1 to 15 digits and cannot start with0.
GET /v1/destination-countries lists every country a rule can name, with its iso_code,
calling_code, continent and shared_code. A country with "shared_code": true cannot have a
country rule; use a prefix rule instead.
A new policy starts with one rule that allows Nigeria (NG).
How rules are evaluated
For each call, the most specific matching rule wins: a longer prefix beats a shorter one. When an allow rule and a deny rule are equally specific, the deny rule wins. A number no rule allows is refused.
For example, with these rules:
| Rule | Effect |
|---|---|
Country NG (calling code 234) | Allow |
Prefix 23480912 | Deny |
a call to +2348034128890 is allowed by NG, and a call to +2348091234567 is refused because the
deny rule 23480912 is more specific.
Change rules
Send changes to PATCH /v1/outbound-policies/{policy_id}/destination-rules with If-Match and
Idempotency-Key. The policy ETag is its revision as a quoted integer, such as "1". Each change has an op of allow, deny or remove, a kind of country or
prefix, a value, and an optional label of 1 to 80 characters:
Code
The response is the policy with its updated rules (trimmed), and a new ETag of "2":
Code
- Send 1 to 250 changes per request. A destination may appear only once in a request.
- Changes are keyed by kind and value, so sending the same change twice leaves one rule.
- Allowed rules also show
rate_minor,rate_unitand the billing increments from your project's price book. - A denied rule with
"source": "containment"was added by Signals fraud containment and carries acase_ref. You cannot remove it yourself.
Rule changes are live once saved. Calls already in progress keep the terms they started with; new calls use the new rules.
Attachments
An attachment links a policy to a service, such as a trunk. A service has at most one policy at a time.
Attach a policy to a trunk
You can attach a policy when you create the trunk, with outbound_policy_id in the create request.
To attach or replace it later, use the trunk's ETag:
Code
- The response is
200 OKwith the trunk, itspolicyset to the new policy, and a new ETag. - Send
{ "policy_id": null }to remove the policy. - The change reaches the network within a minute.
List attachments
GET /v1/outbound-policies/{policy_id}/attachments lists the services using a policy, with
service_type, service_id, service_name, attached_at, calls_in_flight and an apply_state
of applied or pending. A pending attachment is a saved change that has not reached the network
yet.
Attachment IDs start with pat_. To move a trunk to another policy, attach the replacement with
PUT /v1/trunks/{trunk_id}/outbound-policy. To remove a trunk's policy, send { "policy_id": null }
there; the trunk then refuses outbound calls.
Delete a policy
DELETE /v1/outbound-policies/{policy_id} with Idempotency-Key archives the policy and returns
204 No Content. It returns 409 outbound_policy_attached while any service is attached. Replace
the policy on every trunk first, or send ?detach=true to detach every service in the same request.
Detached trunks then refuse outbound calls.
Errors you may see
| Status and code | Cause |
|---|---|
409 outbound_policy_name_conflict | Another policy has this name. |
409 recording_consent_required | recording_mode is all but your organization has not accepted the recording terms. |
409 outbound_policy_attached | The policy is attached to a service and cannot be deleted without detach=true. |
409 idempotency_conflict | The Idempotency-Key was used before with a different body. |
412 outbound_policy_revision_conflict | The If-Match ETag is stale. Read the policy again. |
428 precondition_required | The request has no If-Match header. |
422 invalid_outbound_policy | A field is invalid, for example a prefix starting with 0 or a retention of 60 days. |
Related
- Quickstart creates a policy and attaches it to a new trunk.
- SIP Trunking API reference