You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Customers can now set, read, and clear the outbound caller ID name (CNAM) on a phone number over the REST API. Previously CNAM could only be set from the dashboard (Phone Numbers → a number → Caller ID Name).
A CNAM is not applied instantly. POST queues the requested name for a compliance review, and the response comes back with status: "pending". Background processing then moves the request to approved (the name is set at the carrier and on the number), in_review (a human needs to look at it), rejected, or failed. Clients poll GET to see where a request landed.
Note
CNAM is only available on numbers whose carrier supports it (currently 10DLC numbers). Any request against another number is rejected with 422.
GET returns the most recent CNAM request for the number, not the name currently live at the carrier. The live value is the cnam attribute on the phone number object (GET /api/relay/rest/phone_numbers/{id}). These differ while a request is pending or after one is rejected.
This is unrelated to the existing CNAM lookup endpoint (GET /api/relay/rest/lookup/phone_number/{e164}), which reads a third party's caller ID name rather than setting your own.
Authentication & scope
Auth: HTTP Basic auth: Project ID as the username, API token as the password.
Required scope:numbers. A token without it receives 401 Unauthorized (plain-text body Unauthorized, not a JSON error envelope).
Base URL:https://<your-space>.signalwire.com
Scoped to the caller's project: phone_number_id values belonging to another project return 404 Not Found. An unverified company also receives 401 with{"message": "Please validate a phone number to access your account."}.
CNAM is only supported on numbers from carriers that offer it. Other numbers get 422 with Caller ID name isn't available for this number.
The name is capped at 15 characters after normalization → 422.
Allowed characters after normalization: A–Z, 0–9, space, and & ' . , -. The first character must be a letter or digit → 422.
Names are normalized before validation and storage: control characters removed, runs of whitespace collapsed, then upper-cased. " acme plumbing " is stored and returned as "ACME PLUMBING". Validate against the normalized form, not the input.
POST is not instant. 201 Created means queued for review, not applied. Poll GET until status is approved, rejected, or failed.
One live request per number: a new POST supersedes any earlier pending orin_review request for that number. Re-posting a name that is already approved returns the existing approved request rather than re-running review.
DELETE requires something to clear — an applied name or a request awaiting a decision. Otherwise 422 with There is no caller ID name to clear for this number. Like POST, it is asynchronous: 204 means the clear was queued.
GET returns 404 for a number that has never had a CNAM requested.
reason is only populated for in_review, rejected, and failed requests; it is null for pending and approved.
Fields
CNAM object (returned by GET and POST)
Field
Type
Notes
type
string
Always "cnam".
id
string (UUID)
ID of the CNAM request.
phone_number_id
string (UUID)
The phone number this request belongs to.
name
string
The normalized caller ID name (upper-cased, max 15 chars).
status
string
One of pending, approved, in_review, rejected, failed. See below.
reason
string | null
Machine-readable reason code when the request was not approved.
required_action
string | null
Human-readable next step, when review produced one (e.g. what to verify or document).
created_at
string (ISO 8601)
updated_at
string (ISO 8601)
status values
Value
Meaning
pending
Queued for compliance review.
approved
Approved and set at the carrier. This is the name callers see.
in_review
Automated review could not approve it; awaiting a manual decision.
rejected
Not allowed. Submit a different name.
failed
Processing failed after retries. Safe to submit again.
reason codes
Code
Meaning
offensive_language
Contains language that can't be displayed on calls.
impersonation
Appears to impersonate another person or organization.
unverified_brand
Can't yet confirm the name belongs to the business.
implied_trusted_institution
Implies a bank, government agency, or similar institution.
scam_wording
Wording commonly associated with scam calls.
deceptive
Misleading about who is calling.
unsupported_personal_name
A personal name not supported by verified business details.
too_generic
Too generic to identify the caller.
invalid_format
Characters or formatting that can't be displayed.
unrelated_to_business
Doesn't appear to relate to the verified business.
needs_documentation
Documentation of authorization to use the name is required.
Required. Desired caller ID name. Normalized to upper case; max 15 characters after normalization; A–Z 0–9, space, and & ' . , - only, starting with a letter or digit.
Request / response examples
Fetch the current CNAM request: GET /api/relay/rest/phone_numbers/{phone_number_id}/cnam
Response 204 No Content (no body; the clear is queued)
Error responses
Validation failures (422) return the standard Relay REST error envelope — an errors
array of objects with detail, status, title, and code:
{
"errors": [
{
"detail": "Name is too long (maximum is 15 characters)",
"status": "422",
"title": "Invalid Attribute",
"code": "422"
}
]
}
Auth and lookup failures are plain-text, matching the rest of Relay REST: 401 returns Unauthorized, 404 returns Not Found.
Error codes to document
HTTP
Code
When it happens
401
—
Missing or invalid Basic credentials, or a token without the numbers scope. Plain-text body Unauthorized.
401
—
Company is not verified: {"message": "Please validate a phone number to access your account."}
404
—
phone_number_id doesn't exist or isn't in the caller's project (all three endpoints), or — on GET — the number has never had a caller ID name requested.
422
422
POST / DELETE: the number's carrier doesn't support CNAM — Caller ID name isn't available for this number.
422
422
POST: name missing or empty — Name can't be blank
422
422
POST: normalized name exceeds 15 characters — Name is too long (maximum is 15 characters)
422
422
POST: normalized name has disallowed characters, or doesn't start with a letter or digit — Name can only contain letters, numbers, spaces, and & ' . , -
422
422
POST: the request could not be recorded, safe to retry — Could not queue the caller ID name for review
422
422
DELETE: no applied name and no request awaiting a decision — There is no caller ID name to clear for this number.
All of these reuse the generic 422 code, so no new entries are needed in the public
REST error-code reference. The reason codes in the CNAM object are a separate
enumeration and should be documented on this page (table above), not in the error-code
reference.
OpenAPI Spec
openapi: 3.0.3info:
title: SignalWire Relay REST — Caller ID Name (CNAM)version: "1.0.0"servers:
- url: https://{space}.signalwire.com/api/relay/restvariables:
space:
default: examplepaths:
/phone_numbers/{phone_number_id}/cnam:
parameters:
- name: phone_number_idin: pathrequired: truedescription: ID of the phone number.schema:
type: stringformat: uuidget:
summary: Get the caller ID name request for a phone numberdescription: > Returns the most recent CNAM request for the number. This is not necessarily the name live at the carrier — read `cnam` on the phone number object for that.operationId: getPhoneNumberCnamtags: [Caller ID Name]security:
- basicAuth: []responses:
"200":
description: The most recent CNAM request.content:
application/json:
schema:
$ref: "#/components/schemas/Cnam""401":
$ref: "#/components/responses/Unauthorized""404":
$ref: "#/components/responses/NotFound"post:
summary: Request a caller ID name for a phone numberdescription: > Queues the name for compliance review. A `201` means the request was accepted for review, not that the name is live. Poll `GET` until `status` is `approved`, `rejected`, or `failed`. Supersedes any earlier request still awaiting a decision.operationId: createPhoneNumberCnamtags: [Caller ID Name]security:
- basicAuth: []requestBody:
required: truecontent:
application/json:
schema:
$ref: "#/components/schemas/CnamRequestBody"responses:
"201":
description: The name was queued for review.content:
application/json:
schema:
$ref: "#/components/schemas/Cnam""401":
$ref: "#/components/responses/Unauthorized""404":
$ref: "#/components/responses/NotFound""422":
$ref: "#/components/responses/ValidationError"delete:
summary: Clear the caller ID name on a phone numberdescription: > Queues removal of the caller ID name at the carrier and cancels any request still awaiting a decision.operationId: deletePhoneNumberCnamtags: [Caller ID Name]security:
- basicAuth: []responses:
"204":
description: The clear was queued."401":
$ref: "#/components/responses/Unauthorized""404":
$ref: "#/components/responses/NotFound""422":
$ref: "#/components/responses/ValidationError"components:
securitySchemes:
basicAuth:
type: httpscheme: basicdescription: Project ID as the username, API token as the password. Requires the `numbers` scope.schemas:
Cnam:
type: objectrequired: [type, id, phone_number_id, name, status, created_at, updated_at]properties:
type:
type: stringenum: [cnam]id:
type: stringformat: uuidphone_number_id:
type: stringformat: uuidname:
type: stringmaxLength: 15example: ACME PLUMBINGstatus:
type: stringenum: [pending, approved, in_review, rejected, failed]reason:
type: stringnullable: trueenum:
- offensive_language
- impersonation
- unverified_brand
- implied_trusted_institution
- scam_wording
- deceptive
- unsupported_personal_name
- too_generic
- invalid_format
- unrelated_to_business
- needs_documentation
- other_compliance_concern
- processing_failedrequired_action:
type: stringnullable: truecreated_at:
type: stringformat: date-timeupdated_at:
type: stringformat: date-timeCnamRequestBody:
type: objectrequired: [name]properties:
name:
type: stringdescription: > Desired caller ID name. Normalized before validation — control characters removed, whitespace collapsed, upper-cased.maxLength: 15pattern: "^[A-Z0-9][A-Z0-9 &'.,\\-]*$"example: ACME PLUMBINGError:
type: objectproperties:
errors:
type: arrayitems:
type: objectproperties:
detail:
type: stringstatus:
type: stringexample: "422"title:
type: stringexample: Invalid Attributecode:
type: stringexample: "422"responses:
Unauthorized:
description: Missing or invalid credentials, missing `numbers` scope, or unverified company.content:
text/plain:
schema:
type: stringexample: UnauthorizedNotFound:
description: The phone number is not in this project, or has no CNAM request.content:
text/plain:
schema:
type: stringexample: Not FoundValidationError:
description: The request could not be processed.content:
application/json:
schema:
$ref: "#/components/schemas/Error"
references https://github.com/signalwire/cloud-product/issues/20618
Summary
Customers can now set, read, and clear the outbound caller ID name (CNAM) on a phone number over the REST API. Previously CNAM could only be set from the dashboard (Phone Numbers → a number → Caller ID Name).
A CNAM is not applied instantly.
POSTqueues the requested name for a compliance review, and the response comes back withstatus: "pending". Background processing then moves the request toapproved(the name is set at the carrier and on the number),in_review(a human needs to look at it),rejected, orfailed. Clients pollGETto see where a request landed.Note
422.GETreturns the most recent CNAM request for the number, not the name currently live at the carrier. The live value is thecnamattribute on the phone number object (GET /api/relay/rest/phone_numbers/{id}). These differ while a request is pending or after one is rejected.GET /api/relay/rest/lookup/phone_number/{e164}), which reads a third party's caller ID name rather than setting your own.Authentication & scope
numbers. A token without it receives401 Unauthorized(plain-text bodyUnauthorized, not a JSON error envelope).https://<your-space>.signalwire.comScoped to the caller's project:
phone_number_idvalues belonging to another project return404 Not Found. An unverified company also receives401with{"message": "Please validate a phone number to access your account."}.Endpoints
GET/api/relay/rest/phone_numbers/{phone_number_id}/cnamPOST/api/relay/rest/phone_numbers/{phone_number_id}/cnamDELETE/api/relay/rest/phone_numbers/{phone_number_id}/cnamLimitations
422withCaller ID name isn't available for this number.422.A–Z,0–9, space, and& ' . , -. The first character must be a letter or digit →422." acme plumbing "is stored and returned as"ACME PLUMBING". Validate against the normalized form, not the input.POSTis not instant.201 Createdmeans queued for review, not applied. PollGETuntilstatusisapproved,rejected, orfailed.POSTsupersedes any earlierpendingorin_reviewrequest for that number. Re-posting a name that is alreadyapprovedreturns the existing approved request rather than re-running review.DELETErequires something to clear — an applied name or a request awaiting a decision. Otherwise422withThere is no caller ID name to clear for this number.LikePOST, it is asynchronous:204means the clear was queued.GETreturns404for a number that has never had a CNAM requested.reasonis only populated forin_review,rejected, andfailedrequests; it isnullforpendingandapproved.Fields
CNAM object (returned by
GETandPOST)type"cnam".idphone_number_idnamestatuspending,approved,in_review,rejected,failed. See below.reasonrequired_actioncreated_atupdated_atstatusvaluespendingapprovedin_reviewrejectedfailedreasoncodesoffensive_languageimpersonationunverified_brandimplied_trusted_institutionscam_wordingdeceptiveunsupported_personal_nametoo_genericinvalid_formatunrelated_to_businessneeds_documentationother_compliance_concernprocessing_failedstatus: "failed"— processing errored, retry.Writable fields (
POSTrequest body)nameA–Z 0–9, space, and& ' . , -only, starting with a letter or digit.Request / response examples
Fetch the current CNAM request:
GET /api/relay/rest/phone_numbers/{phone_number_id}/cnamRequest
Response
200 OK{ "type": "cnam", "id": "b6a4f0c2-3f1e-4c9a-9c1b-7f2e5a1d8c40", "phone_number_id": "1cf0a2a0-8a6b-4a7c-9d63-3d1b6f0f2f11", "name": "ACME PLUMBING", "status": "approved", "reason": null, "required_action": null, "created_at": "2026-06-24T14:02:11Z", "updated_at": "2026-06-24T14:04:53Z" }Response
200 OK(held for manual review){ "type": "cnam", "id": "c81b25de-9f4a-4d2f-8e5c-0a6b1c2d3e4f", "phone_number_id": "1cf0a2a0-8a6b-4a7c-9d63-3d1b6f0f2f11", "name": "ACME BANK", "status": "in_review", "reason": "implied_trusted_institution", "required_action": "Provide documentation showing you are authorized to use this name.", "created_at": "2026-06-24T15:10:02Z", "updated_at": "2026-06-24T15:10:19Z" }Request a caller ID name:
POST /api/relay/rest/phone_numbers/{phone_number_id}/cnamRequest
{ "name": "ACME PLUMBING" }Response
201 Created{ "type": "cnam", "id": "b6a4f0c2-3f1e-4c9a-9c1b-7f2e5a1d8c40", "phone_number_id": "1cf0a2a0-8a6b-4a7c-9d63-3d1b6f0f2f11", "name": "ACME PLUMBING", "status": "pending", "reason": null, "required_action": null, "created_at": "2026-06-24T14:02:11Z", "updated_at": "2026-06-24T14:02:11Z" }Clear the caller ID name:
DELETE /api/relay/rest/phone_numbers/{phone_number_id}/cnamRequest
Response
204 No Content(no body; the clear is queued)Error responses
Validation failures (
422) return the standard Relay REST error envelope — anerrorsarray of objects with
detail,status,title, andcode:{ "errors": [ { "detail": "Name is too long (maximum is 15 characters)", "status": "422", "title": "Invalid Attribute", "code": "422" } ] }Auth and lookup failures are plain-text, matching the rest of Relay REST:
401returnsUnauthorized,404returnsNot Found.Error codes to document
numbersscope. Plain-text bodyUnauthorized.{"message": "Please validate a phone number to access your account."}phone_number_iddoesn't exist or isn't in the caller's project (all three endpoints), or — onGET— the number has never had a caller ID name requested.422POST/DELETE: the number's carrier doesn't support CNAM —Caller ID name isn't available for this number.422POST:namemissing or empty —Name can't be blank422POST: normalized name exceeds 15 characters —Name is too long (maximum is 15 characters)422POST: normalized name has disallowed characters, or doesn't start with a letter or digit —Name can only contain letters, numbers, spaces, and & ' . , -422POST: the request could not be recorded, safe to retry —Could not queue the caller ID name for review422DELETE: no applied name and no request awaiting a decision —There is no caller ID name to clear for this number.All of these reuse the generic
422code, so no new entries are needed in the publicREST error-code reference. The
reasoncodes in the CNAM object are a separateenumeration and should be documented on this page (table above), not in the error-code
reference.
OpenAPI Spec