---
title: "Preflight an outbound call or SMS against the pre-dial gates, persisting nothing"
method: POST
path: "/v1/policies/authorize-outbound"
---

# Preflight an outbound call or SMS against the pre-dial gates, persisting nothing

`POST /v1/policies/authorize-outbound`

## Request

- Base URL: `https://api.skysay.ai`
- URL: `https://api.skysay.ai/v1/policies/authorize-outbound`
- Auth: none declared

Answers whether POST /v1/calls (or an SMS send) would be refused before dialling, without creating anything. For `channel` `outbound_voice` (the default) it asks both pre-dial questions a call meets, in the same order: first the workspace capabilities (destination country, channel, use-case profile, review signals, caps), then, only if those allow it, the per-call outbound policy (`purpose`, `user_authorization` with both `authorized_by` and `reason`, caller-number readiness, the destination format). `stage` says which question answered: `outbound_authorization` or `outbound_policy`. For any other channel (`sms`) only the capabilities question is asked. This is a preflight of those two gates, not a full admission: number rules, plan concurrency, maintenance windows and the wallet reservation are not evaluated; spend caps are checked only against the `amount_minor` you send, calling rules only when you send `project_id`, and caller-number readiness only when you send `from_number_id` (the call itself always needs one).

## Request body

- object
  - `amount_minor` integer: Estimated cost to check spend caps against; 0 skips them.
  - `bulk` boolean
  - `campaign_id` string
  - `categories` string[]
  - `channel` string: `outbound_voice` (the default) or `sms`; any value other than `outbound_voice` is judged as SMS.
  - `from_number_id` string: The caller number; it must belong to the organization (and to `project_id` when sent).
  - `metadata` object: Alternatively, every field above except organization_id, channel, to, from_number_id and amount_minor, nested here.
  - `organization_id` string, required
  - `policy` object: The same `policy` object POST /v1/calls takes.
  - `project_id` string
  - `purpose` string
  - `recipient_type` string
  - `relationship` string
  - `to` string: Destination in E.164. `phone_number` is accepted as the same field.
  - `user_authorization` object: Who approved the call and why. Both fields are required on every outbound call.
    - `authorized_by` string
    - `reason` string

## Response `200`

The decision the first refusing gate gave, or `allowed` when both allow.

- object
  - `capabilities_snapshot` object
  - `customer_reason` string, required
  - `decision` 'allowed' | 'blocked' | 'needs_review', required
  - `escalation_signals` string[], required: Every reason code the refusing gate gave.
  - `next_action` string, required
  - `policy` object: The per-call policy evaluation; present whenever the voice policy question was asked.
    - `allowed` boolean
    - `reasons` string[]
    - `required_actions` string[]: What to add or do. `provide_user_authorization.authorized_by` and `provide_user_authorization.reason` name a missing user_authorization field.
    - `risk_level` string
  - `reason_code` string, required: `authorized` when allowed; otherwise the refusing gate's first reason code.
  - `stage` 'outbound_authorization' | 'outbound_policy', required: Which gate gave the decision.

## Other responses

- `400`: A malformed request, or a from_number_id that belongs to another organization or project.
- `404`: from_number_id does not exist.

---

[API](https://skmtc.dev/skysay/apis/skysay-api.md) · [All operations](https://skmtc.dev/skysay/apis/skysay-api/llms.txt) · [OpenAPI document](https://skmtc.dev/skysay/apis/skysay-api/revisions/148c7e111260?raw)
