photon account 10dlc registers and maintains your organization’s 10DLC
brands and campaigns. Registration starts the moment a command succeeds — there is no
local draft and no separate submit step.
Brands and campaigns belong to the
selected organization: your stored
organization, your only organization, or --org for one invocation. The global --project option does not scope them.
Browse the automatic command reference.
The workflow
Use truthful business and contact information that matches government, tax-authority, and other official records. Mismatches delay registration or get it rejected.1
Register a brand
Supply a complete organization or sole-proprietor profile. Registration
begins as soon as
create is accepted.2
Verify the OTP, for a sole proprietor
Send and verify the code for the registrant phone once the brand status
says verification is available.
3
Monitor the brand
brand view shows registration feedback so you can fix rejected
information. Use brand edit to start a correction. Photon may verify the
correction automatically or ask for another OTP.4
Register a campaign
Describe the real use cases, consent flow, and representative messages.Photon may hold the campaign awaiting brand verification or qualification,
then submit it automatically once the brand is eligible.
5
Assign a phone number
Assign a sending number to the approved campaign through the appropriate
Photon workflow before you send A2P traffic.
create and edit confirm before reading private input. Registration warns
that it begins immediately; correction warns that the current profile stays
active until Photon accepts the replacement. Scripts must pass --force.
Brand profiles
create requires a complete profile. In an interactive terminal with no
--profile-file, it walks you through every required field:
Organization profile
Organization profile
Every field is required.
entityType accepts only private_profit or
non_profit.Sole-proprietor profile
Sole-proprietor profile
A reduced schema. The phone must be a US
+1 number that can receive SMS.Supported vertical values
Supported vertical values
agriculture, communication, construction, education, energy,
entertainment, financial, gambling, government, healthcare,
hospitality, human_resources, insurance, legal, manufacturing,
ngo, political, postal, professional, real_estate, retail,
technology, transportation.Correct a brand
A normaledit is a partial profile. It must carry type as the discriminator
plus at least one editable field:
edit --replace sends a complete profile, so it requires --profile-file in
an interactive terminal — that keeps write-only EIN and phone values explicit
rather than reconstructed from redacted data.
Brand type is immutable either way. Edits return immediately as
{"brand": ...}, and the existing profile stays active until Photon accepts
the correction.
Privacy policy and terms URLs belong to the campaign, not the brand profile.
Register a campaign
Before you prepare campaign input, read the CTIA Messaging Principles and Best Practices and The Campaign Registry’s campaign guidance. Describe the real subscriber experience: how consent is obtained, how the sender is identified, how HELP and STOP work, where the privacy policy and terms live, and what your messages actually look like.The CLI validates the structural contract and offers guidance. It does not
guarantee approval and does not replace legal or compliance review.
2FA, ACCOUNT_NOTIFICATION, CUSTOMER_CARE,
DELIVERY_NOTIFICATION, FRAUD_ALERT, HIGHER_EDUCATION, MARKETING,
POLLING_VOTING, PUBLIC_SERVICE_ANNOUNCEMENT, and SECURITY_ALERT. Select
1–5 distinct purposes; order does not matter. The catalog response also reports
the current minimum and maximum selection counts.
Campaign document
Campaign document
name is a caller-owned label of 1–64 characters that Photon
never submits to the registry. Descriptions are 40–4,096 characters and message flows are 40–2,048
characters. Supply 2–5 ordered representative messages of 20–255 characters,
with at least one sample per selected use case. Internal newlines are
preserved; other control and format characters are rejected. Unknown and
legacy registry fields are rejected.All four attestations must be explicitly true. An embedded link sample must
be a safe absolute HTTP(S) URL with no credentials or fragment, and is
allowed only when embeddedLinks is true.Filter campaigns
awaiting_brand_verification,
awaiting_brand_qualification, submitting, reviewing, action_required,
activating, ready, suspended, expired, and support_required. The two
awaiting states mean Photon will submit automatically once the brand
prerequisite completes. Returned status strings stay opaque so new server
states still display.
Update a campaign
Runcampaign view first. The response includes etag,
capabilities.editableFields, capabilities.canResubmit,
hasUnsubmittedChanges, and review feedback.
Use the returned ETag to protect against overwriting a newer campaign revision.
campaign-update.json:
etag, updateMask, and the fields to replace:
--sample-message 2–5 times to replace the full sample set.
How edits take effect depends on the campaign state:
- Name changes are local and allowed in every state.
- Eligible rejected campaigns save content changes locally until resubmission.
- Ready campaigns allow asynchronous sample updates; the approved samples stay live until the registry applies the replacement.
- Other states lock campaign content. Check
capabilities.editableFieldsbefore editing andcapabilities.canResubmitbefore resubmitting.
Resubmit a campaign
Edit the campaign first, then fetch its current ETag. Resubmit only whencapabilities.canResubmit is true. The old campaign correct endpoint was
replaced by separate edit and resubmit operations.
etag is required. appealReason is optional and, when supplied, must be
20–2,000 characters. Resubmission does not accept campaign edits. Automation
may pipe the same JSON through stdin. The CLI confirms before resubmission,
which may incur another registration fee.
Sole-proprietor OTP
verify
prompts for the 4–10-character alphanumeric code without echoing it.
Raw OTP codes, full phone numbers, EINs, profile contents, and registration
feedback are excluded from errors, --debug diagnostics, and the local
journal. brand view deliberately still shows registration feedback, since
that is what you need to correct a rejection.
Output and recovery
JSON uses stable, selected envelopes:
IDs are exposed as
brandId and campaignId. Undocumented response fields are
omitted, and statuses stay opaque strings.
Brand create, brand edit, and OTP verification are not journaled, because
replaying them would require sensitive input. Their idempotency key exists only
in memory. If an outcome is uncertain, the error includes that key — check the
current state, then rerun the exact command and private input with the same
--idempotency-key.
OTP send and campaign mutations do use the journal. Campaign records keep the
normalized input and its digest but never file paths, and descriptions, message
flows, samples, and appeal text are redacted from operation view, errors, and
diagnostics. That means a replay needs only the operation ID: