Telephony API
REST endpoints for telephony in SKUFlow: 13 operations with parameters, request and response fields, permissions and curl examples.
Base URL: https://app.skuflow.ai/api. Every call needs Authorization: Bearer skf_… (Authentication); {organizationId} ($ORGANIZATION_ID in the examples) is your business's id.
| Operation | Endpoint | Risk |
|---|---|---|
| Telephony account status | GET /organizations/{organizationId}/telephony | read |
| Choose the Twilio account | POST /organizations/{organizationId}/telephony/source | sensitive |
| Find a texting number | GET /organizations/{organizationId}/telephony/numbers/available | read |
| Text through SKUFlow | POST /organizations/{organizationId}/telephony/texting | sensitive |
| Can the texting number be replaced | GET /organizations/{organizationId}/telephony/texting/replacement | read |
| Replace the texting number | POST /organizations/{organizationId}/telephony/texting/replace | sensitive |
| A2P 10DLC registration | GET /organizations/{organizationId}/telephony/a2p | read |
| Register for A2P 10DLC | POST /organizations/{organizationId}/telephony/a2p | sensitive |
| Check an A2P registration before submitting | GET /organizations/{organizationId}/telephony/a2p/readiness | read |
| Resend the sole proprietor confirmation text | POST /organizations/{organizationId}/telephony/a2p/otp | sensitive |
| Check the A2P status now | POST /organizations/{organizationId}/telephony/a2p/refresh | write |
| Telephony usage this month | GET /organizations/{organizationId}/telephony/usage | read |
| Run telephony jobs now | POST /organizations/{organizationId}/telephony/run | write |
Telephony account status
GET /organizations/{organizationId}/telephony
Which Twilio account the business's calls and texts run on (MANAGED: its SKUFlow sub-account, billed at Twilio's cost + 20%; OWN: its own Twilio account), the sub-account's state (ACTIVE, SUSPENDED while the SKUFlow subscription is unpaid or cancelled, CLOSED), the managed texting number, the A2P 10DLC status, numbers scheduled for release and warnings for the owner. Read-only.
| Permission | channels.manage (Owner, Admin) |
| Risk | read, OAuth scope skuflow.read. Read: reads only. |
| MCP tool | telephony_status (toolset settings) |
Example
curl "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/telephony" \
-H "Authorization: Bearer $SKUFLOW_API_KEY"Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
mode | enum | SKUFLOW_TWILIO on this server (fake = simulated). One of fake, live, off. |
source | enum | Managed: numbers, minutes and texts from SKUFlow (Twilio sub-account, billed at Twilio's cost + 20%). OWN: the business's own Twilio account (connected in Settings → Messaging). One of MANAGED, OWN. |
subaccount | object or null | The SKUFlow sub-account; null until the phone system or managed texting is first turned on. |
subaccount.accountSidHint | string | Last characters of the sub-account SID. |
subaccount.status | enum | One of ACTIVE, SUSPENDED, CLOSED. |
subaccount.fake | boolean | |
subaccount.suspendReason | string or null | UNPAID or CANCELED. |
subaccount.suspendedAt | string (date-time) or null | |
subaccount.closeAfter | string (date-time) or null | Numbers are released then unless the subscription is restarted. |
subaccount.closedAt | string (date-time) or null | |
subaccount.createdAt | string (date-time) | |
texting | object | |
texting.providerKey | string | skuflow (managed), twilio (own account) or test. |
texting.number | object or null | |
texting.number.id | string | |
texting.number.e164 | string | |
texting.number.label | string | |
a2pStatus | enum | One of NOT_STARTED, PROFILE_SUBMITTED, BRAND_PENDING, OTP_PENDING, BRAND_APPROVED, CAMPAIGN_PENDING, APPROVED, FAILED. |
releasing | array of object | |
releasing[].id | string | |
releasing[].e164 | string | |
releasing[].releaseAfter | string (date-time) | |
warnings | array of object | |
warnings[].kind | enum | One of SUSPENDED, CLOSING, NUMBERS_RELEASING, A2P_REQUIRED, A2P_FAILED. |
warnings[].message | string | |
warnings[].at | string (date-time) or null | |
trial | object | The free trial's telephony limits. |
trial.limited | boolean | The free trial's limits apply (no card). |
trial.limits | object | |
trial.limits.numbers | number | |
trial.limits.callMinutes | number | |
trial.usage | object | |
trial.usage.numbers | number | |
trial.usage.callMinutes | number | |
trial.canAddNumber | boolean | |
trial.callsPaused | boolean | |
trial.messages | array of string | What is paused, in plain words. |
autoNumber | object | The automatic texting number bought for every new business. |
autoNumber.status | enum | pending / provisioning: SKUFlow is getting the business's texting number; done: it has one (e164); failed: retried automatically (error, nextAttemptAt); off: none is bought automatically (skipReason). One of pending, provisioning, done, failed, off. |
autoNumber.e164 | string or null | |
autoNumber.error | string or null | |
autoNumber.skipReason | string or null | OWN_ACCOUNT, HAS_TEXTING or SUBSCRIPTION_INACTIVE when skipped. |
autoNumber.nextAttemptAt | string (date-time) or null |
Choose the Twilio account
POST /organizations/{organizationId}/telephony/source
Money: MANAGED moves calls (and, once a SKUFlow texting number is chosen, texts) to the business's SKUFlow Twilio sub-account, made now if needed; numbers, minutes and other usage are then billed at Twilio's cost + 20%. Turning MANAGED on needs the owner's acceptance of the phone system's usage terms: a current one on record, or acknowledgement with the priceVersion shown (billing.plan → addons[phone].terms); otherwise 409 with the current terms. OWN goes back to the business's own Twilio account (it must be connected in Settings → Messaging first). Numbers already set up stay where they are.
| Permission | phone.manage (Owner, Admin) |
| Risk | sensitive, OAuth scope skuflow.sensitive. Sensitive: moves money, deletes, sends or shows something to a customer, or grants or revokes access. |
| MCP tool | telephony_chooseSource (toolset settings) |
| Approval | Waits for your approval in SKUFlow when called with an API key or a connected app: the first call answers 428 APPROVAL_REQUIRED; once you approve it, repeat the call with the X-SKUFlow-Approval header. See Approvals. |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
source | enum | Yes | Managed: numbers, minutes and texts from SKUFlow (Twilio sub-account, billed at Twilio's cost + 20%). OWN: the business's own Twilio account (connected in Settings → Messaging). One of MANAGED, OWN. |
acknowledgement | object | No | The owner's acceptance of the terms shown (billing.plan → addons[].terms). Missing or stale: 409 with the current terms. |
acknowledgement.priceVersion | string | Yes | terms.priceVersion as it was shown. Up to 64 characters. |
acknowledgement.accepted | true | Yes | The owner ticked “I understand usage is billed on top of the monthly fee”. |
Example
curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/telephony/source" \
-H "Authorization: Bearer $SKUFLOW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"source":"MANAGED"}'Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
mode | enum | SKUFLOW_TWILIO on this server (fake = simulated). One of fake, live, off. |
source | enum | Managed: numbers, minutes and texts from SKUFlow (Twilio sub-account, billed at Twilio's cost + 20%). OWN: the business's own Twilio account (connected in Settings → Messaging). One of MANAGED, OWN. |
subaccount | object or null | The SKUFlow sub-account; null until the phone system or managed texting is first turned on. |
subaccount.accountSidHint | string | Last characters of the sub-account SID. |
subaccount.status | enum | One of ACTIVE, SUSPENDED, CLOSED. |
subaccount.fake | boolean | |
subaccount.suspendReason | string or null | UNPAID or CANCELED. |
subaccount.suspendedAt | string (date-time) or null | |
subaccount.closeAfter | string (date-time) or null | Numbers are released then unless the subscription is restarted. |
subaccount.closedAt | string (date-time) or null | |
subaccount.createdAt | string (date-time) | |
texting | object | |
texting.providerKey | string | skuflow (managed), twilio (own account) or test. |
texting.number | object or null | |
texting.number.id | string | |
texting.number.e164 | string | |
texting.number.label | string | |
a2pStatus | enum | One of NOT_STARTED, PROFILE_SUBMITTED, BRAND_PENDING, OTP_PENDING, BRAND_APPROVED, CAMPAIGN_PENDING, APPROVED, FAILED. |
releasing | array of object | |
releasing[].id | string | |
releasing[].e164 | string | |
releasing[].releaseAfter | string (date-time) | |
warnings | array of object | |
warnings[].kind | enum | One of SUSPENDED, CLOSING, NUMBERS_RELEASING, A2P_REQUIRED, A2P_FAILED. |
warnings[].message | string | |
warnings[].at | string (date-time) or null | |
trial | object | The free trial's telephony limits. |
trial.limited | boolean | The free trial's limits apply (no card). |
trial.limits | object | |
trial.limits.numbers | number | |
trial.limits.callMinutes | number | |
trial.usage | object | |
trial.usage.numbers | number | |
trial.usage.callMinutes | number | |
trial.canAddNumber | boolean | |
trial.callsPaused | boolean | |
trial.messages | array of string | What is paused, in plain words. |
autoNumber | object | The automatic texting number bought for every new business. |
autoNumber.status | enum | pending / provisioning: SKUFlow is getting the business's texting number; done: it has one (e164); failed: retried automatically (error, nextAttemptAt); off: none is bought automatically (skipReason). One of pending, provisioning, done, failed, off. |
autoNumber.e164 | string or null | |
autoNumber.error | string or null | |
autoNumber.skipReason | string or null | OWN_ACCOUNT, HAS_TEXTING or SUBSCRIPTION_INACTIVE when skipped. |
autoNumber.nextAttemptAt | string (date-time) or null |
Find a texting number
GET /organizations/{organizationId}/telephony/numbers/available
US local numbers that can text, available to buy in the business's SKUFlow account, by area code and / or digits or letters inside the number (contains, e.g. 4210 or PRINT), and what the number would cost a month (offer: Twilio's cost + 20%, or included: the texting number is included on every plan). Call before POST /telephony/texting with buyE164 (or POST /telephony/texting/replace to swap the current texting number). Makes the SKUFlow sub-account the first time (no charge until a number is bought).
| Permission | channels.manage (Owner, Admin) |
| Risk | read, OAuth scope skuflow.read. Read: reads only. |
| MCP tool | telephony_availableNumbers (toolset settings) |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
areaCode | query | string | No | Three-digit US area code, e.g. 512. Optional when contains is given. |
contains | query | string | No | Digits or letters the number must contain, anywhere (Twilio Contains): 2–10 of 0-9, A-Z (phone keypad: PRINT = 77468) and * for any one digit, e.g. 4210 or 555****. Spaces and dashes are ignored. With neither field, any US local number. Up to 20 characters. |
Example
curl "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/telephony/numbers/available" \
-H "Authorization: Bearer $SKUFLOW_API_KEY"Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
items | array of object | |
items[].e164 | string | +E.164; pass it as buyE164 / e164 to buy it. |
items[].locality | string or null | Twilio's rate center (city), when known. |
items[].region | string or null | Two-letter state, when known. |
offer | object | What one more number costs the business a month. |
offer.monthlyCents | integer | A local number's monthly price at Twilio's cost + 20%, in cents. |
offer.included | boolean | This number would not be billed (included). |
offer.includedBy | enum or null | Texting: the texting number on every plan; PHONE_ADDON: the phone add-on's number. One of TEXTING, PHONE_ADDON. |
offer.source | enum | Twilio's live price, or the fallback table. One of twilio, fallback. |
Text through SKUFlow
POST /organizations/{organizationId}/telephony/texting
Money, customer-visible: makes the business's texts go out of its SKUFlow Twilio sub-account from phoneNumberId (one of its SKUFlow numbers) or a number bought now (buyE164, from GET /telephony/numbers/available; billed monthly at Twilio's cost + 20%). Replaces the SMS provider in Settings → Messaging (your own Twilio credentials are removed) and switches the business to SKUFlow-managed telephony. Texts keep going through consent, quiet hours and the queue; texts from a live account start once the A2P 10DLC registration is approved.
| Permission | channels.manage (Owner, Admin) |
| Risk | sensitive, OAuth scope skuflow.sensitive. Sensitive: moves money, deletes, sends or shows something to a customer, or grants or revokes access. |
| MCP tool | telephony_setupTexting (toolset settings) |
| Approval | Over MCP, this tool asks for your OK first (in the AI app when it supports it, otherwise in SKUFlow). See Approvals. |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
phoneNumberId | string | No | One of the business's SKUFlow numbers. |
buyE164 | string | No | A number to buy, +E.164. Up to 32 characters. |
label | string | No | Up to 60 characters. |
Example
curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/telephony/texting" \
-H "Authorization: Bearer $SKUFLOW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"phoneNumberId":"phoneNumber_id","buyE164":"string","label":"string"}'Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
mode | enum | SKUFLOW_TWILIO on this server (fake = simulated). One of fake, live, off. |
source | enum | Managed: numbers, minutes and texts from SKUFlow (Twilio sub-account, billed at Twilio's cost + 20%). OWN: the business's own Twilio account (connected in Settings → Messaging). One of MANAGED, OWN. |
subaccount | object or null | The SKUFlow sub-account; null until the phone system or managed texting is first turned on. |
subaccount.accountSidHint | string | Last characters of the sub-account SID. |
subaccount.status | enum | One of ACTIVE, SUSPENDED, CLOSED. |
subaccount.fake | boolean | |
subaccount.suspendReason | string or null | UNPAID or CANCELED. |
subaccount.suspendedAt | string (date-time) or null | |
subaccount.closeAfter | string (date-time) or null | Numbers are released then unless the subscription is restarted. |
subaccount.closedAt | string (date-time) or null | |
subaccount.createdAt | string (date-time) | |
texting | object | |
texting.providerKey | string | skuflow (managed), twilio (own account) or test. |
texting.number | object or null | |
texting.number.id | string | |
texting.number.e164 | string | |
texting.number.label | string | |
a2pStatus | enum | One of NOT_STARTED, PROFILE_SUBMITTED, BRAND_PENDING, OTP_PENDING, BRAND_APPROVED, CAMPAIGN_PENDING, APPROVED, FAILED. |
releasing | array of object | |
releasing[].id | string | |
releasing[].e164 | string | |
releasing[].releaseAfter | string (date-time) | |
warnings | array of object | |
warnings[].kind | enum | One of SUSPENDED, CLOSING, NUMBERS_RELEASING, A2P_REQUIRED, A2P_FAILED. |
warnings[].message | string | |
warnings[].at | string (date-time) or null | |
trial | object | The free trial's telephony limits. |
trial.limited | boolean | The free trial's limits apply (no card). |
trial.limits | object | |
trial.limits.numbers | number | |
trial.limits.callMinutes | number | |
trial.usage | object | |
trial.usage.numbers | number | |
trial.usage.callMinutes | number | |
trial.canAddNumber | boolean | |
trial.callsPaused | boolean | |
trial.messages | array of string | What is paused, in plain words. |
autoNumber | object | The automatic texting number bought for every new business. |
autoNumber.status | enum | pending / provisioning: SKUFlow is getting the business's texting number; done: it has one (e164); failed: retried automatically (error, nextAttemptAt); off: none is bought automatically (skipReason). One of pending, provisioning, done, failed, off. |
autoNumber.e164 | string or null | |
autoNumber.error | string or null | |
autoNumber.skipReason | string or null | OWN_ACCOUNT, HAS_TEXTING or SUBSCRIPTION_INACTIVE when skipped. |
autoNumber.nextAttemptAt | string (date-time) or null |
Can the texting number be replaced
GET /organizations/{organizationId}/telephony/texting/replacement
Before POST /telephony/texting/replace: whether the business's SKUFlow texting number can be swapped for another now, and what happens. Allowed before an A2P 10DLC registration is submitted (or after one refused before the brand was approved): the old number is released afterwards unless something else uses it (oldNumber.keptBecause). Refused while the registration is under review, and for an approved sole proprietor (one number per campaign). After a standard brand is approved the new number joins its Messaging Service first; with an approved campaign the old number is kept. cost says what it adds to the bill. Read-only.
| Permission | channels.manage (Owner, Admin) |
| Risk | read, OAuth scope skuflow.read. Read: reads only. |
| MCP tool | telephony_textingReplacement (toolset settings) |
Example
curl "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/telephony/texting/replacement" \
-H "Authorization: Bearer $SKUFLOW_API_KEY"Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
current | object or null | The texting number today. |
current.id | string | |
current.e164 | string | |
current.label | string | |
allowed | boolean | |
mode | enum or null | BEFORE_REGISTRATION: no A2P campaign holds the number yet. JOIN_CAMPAIGN: the new number joins the approved brand's Messaging Service first. One of BEFORE_REGISTRATION, JOIN_CAMPAIGN. |
refusal | enum or null | Why not: no SKUFlow texting number yet; the A2P registration is under review; a sole proprietor's campaign takes one number; the free trial's one number / one change. One of NO_TEXTING_NUMBER, UNDER_REVIEW, SOLE_PROPRIETOR, TRIAL. |
message | string or null | The refusal in plain words. |
warning | string or null | What to know before replacing (shown in the confirmation). |
oldNumber | object | |
oldNumber.willRelease | boolean | The old number is given back to Twilio after the swap. |
oldNumber.keptBecause | array of enum | |
cost | object | |
cost.monthlyCents | integer | A local number's monthly price at Twilio's cost + 20%, in cents. |
cost.thisMonthCents | integer | About what the swap adds to this month's bill: numbers are billed a month at a time, with no refund for a released one (0 when the phone add-on's included number covers it). |
cost.extraMonthlyCents | integer | Added every month after: the kept old number's price (0 when it is released or included). |
trial | object | |
trial.limited | boolean | |
trial.replacementsLeft | integer or null |
Replace the texting number
POST /organizations/{organizationId}/telephony/texting/replace
Money, customer-visible, destructive: swaps the business's SKUFlow texting number for buyE164 (bought now; from GET /telephony/numbers/available) or phoneNumberId (one of its SKUFlow numbers). Call GET /telephony/texting/replacement first: refused with 409 for the same reasons (A2P registration under review, an approved sole proprietor, the free trial's one change). The new number is in place (and in the A2P Messaging Service when there is one) before texts move to it; then the old number is released back to Twilio unless something else uses it (ring routing, tracking, call history, an approved campaign). Customers see the new number on every text from now on. A number is billed monthly at Twilio's cost + 20% (the texting number is included), with no refund for the released number's month.
| Permission | channels.manage (Owner, Admin) |
| Risk | sensitive, OAuth scope skuflow.sensitive. Sensitive: moves money, deletes, sends or shows something to a customer, or grants or revokes access. |
| MCP tool | telephony_replaceTextingNumber (toolset settings) |
| Approval | Over MCP, this tool asks for your OK first (in the AI app when it supports it, otherwise in SKUFlow). See Approvals. |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
buyE164 | string | No | A number to buy, +E.164. Up to 32 characters. |
phoneNumberId | string | No | One of the business's SKUFlow numbers. |
label | string | No | Name for a bought number. Up to 60 characters. |
Example
curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/telephony/texting/replace" \
-H "Authorization: Bearer $SKUFLOW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"buyE164":"string","phoneNumberId":"phoneNumber_id","label":"string"}'Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
mode | enum | SKUFLOW_TWILIO on this server (fake = simulated). One of fake, live, off. |
source | enum | Managed: numbers, minutes and texts from SKUFlow (Twilio sub-account, billed at Twilio's cost + 20%). OWN: the business's own Twilio account (connected in Settings → Messaging). One of MANAGED, OWN. |
subaccount | object or null | The SKUFlow sub-account; null until the phone system or managed texting is first turned on. |
subaccount.accountSidHint | string | Last characters of the sub-account SID. |
subaccount.status | enum | One of ACTIVE, SUSPENDED, CLOSED. |
subaccount.fake | boolean | |
subaccount.suspendReason | string or null | UNPAID or CANCELED. |
subaccount.suspendedAt | string (date-time) or null | |
subaccount.closeAfter | string (date-time) or null | Numbers are released then unless the subscription is restarted. |
subaccount.closedAt | string (date-time) or null | |
subaccount.createdAt | string (date-time) | |
texting | object | |
texting.providerKey | string | skuflow (managed), twilio (own account) or test. |
texting.number | object or null | |
texting.number.id | string | |
texting.number.e164 | string | |
texting.number.label | string | |
a2pStatus | enum | One of NOT_STARTED, PROFILE_SUBMITTED, BRAND_PENDING, OTP_PENDING, BRAND_APPROVED, CAMPAIGN_PENDING, APPROVED, FAILED. |
releasing | array of object | |
releasing[].id | string | |
releasing[].e164 | string | |
releasing[].releaseAfter | string (date-time) | |
warnings | array of object | |
warnings[].kind | enum | One of SUSPENDED, CLOSING, NUMBERS_RELEASING, A2P_REQUIRED, A2P_FAILED. |
warnings[].message | string | |
warnings[].at | string (date-time) or null | |
trial | object | The free trial's telephony limits. |
trial.limited | boolean | The free trial's limits apply (no card). |
trial.limits | object | |
trial.limits.numbers | number | |
trial.limits.callMinutes | number | |
trial.usage | object | |
trial.usage.numbers | number | |
trial.usage.callMinutes | number | |
trial.canAddNumber | boolean | |
trial.callsPaused | boolean | |
trial.messages | array of string | What is paused, in plain words. |
autoNumber | object | The automatic texting number bought for every new business. |
autoNumber.status | enum | pending / provisioning: SKUFlow is getting the business's texting number; done: it has one (e164); failed: retried automatically (error, nextAttemptAt); off: none is bought automatically (skipReason). One of pending, provisioning, done, failed, off. |
autoNumber.e164 | string or null | |
autoNumber.error | string or null | |
autoNumber.skipReason | string or null | OWN_ACCOUNT, HAS_TEXTING or SUBSCRIPTION_INACTIVE when skipped. |
autoNumber.nextAttemptAt | string (date-time) or null | |
replacement | object | |
replacement.from | string | The old texting number. |
replacement.to | string | The new texting number. |
replacement.oldNumber | object | |
replacement.oldNumber.id | string | |
replacement.oldNumber.e164 | string | |
replacement.oldNumber.released | boolean | |
replacement.oldNumber.keptBecause | array of enum | |
replacement.oldNumber.releaseError | string or null | Twilio refused the release: the number is kept; release it in Settings → Phone. |
A2P 10DLC registration
GET /organizations/{organizationId}/telephony/a2p
The business's A2P 10DLC registration in its SKUFlow sub-account (US carriers require it for texts from business numbers): NOT_STARTED, PROFILE_SUBMITTED, BRAND_PENDING, OTP_PENDING (a sole proprietor must reply YES to the confirmation text), BRAND_APPROVED, CAMPAIGN_PENDING, APPROVED or FAILED (with issues: what Twilio refused, per field, in plain English), what was submitted, and suggestions from the business profile, website and the signed-in person. Read-only.
| Permission | channels.manage (Owner, Admin) |
| Risk | read, OAuth scope skuflow.read. Read: reads only. |
| MCP tool | telephony_a2p (toolset settings) |
Example
curl "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/telephony/a2p" \
-H "Authorization: Bearer $SKUFLOW_API_KEY"Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
status | enum | One of NOT_STARTED, PROFILE_SUBMITTED, BRAND_PENDING, OTP_PENDING, BRAND_APPROVED, CAMPAIGN_PENDING, APPROVED, FAILED. |
brandType | enum | One of STANDARD, SOLE_PROPRIETOR. |
brandStatus | string or null | |
identityStatus | string or null | Twilio's brand identity check: SELF_DECLARED, UNVERIFIED, VERIFIED, VETTED_VERIFIED. |
customerProfileStatus | string or null | Trust Hub customer profile status. |
trustProductStatus | string or null | Trust Hub A2P bundle status. |
campaignStatus | string or null | |
messagingServiceSid | string or null | |
failureReason | string or null | |
issues | array of object | Why it was refused, per field (empty unless FAILED). |
issues[].source | enum | Which step refused it. One of profile, trust, brand, otp, campaign, submit. |
issues[].code | integer or null | Twilio's error code (twilio.com/docs/api/errors/{code}). |
issues[].field | string or null | The registration field to change (e.g. ein, messageFlow, sampleMessages.0). |
issues[].message | string | What to fix, in plain English. |
issues[].detail | string or null | Twilio's own words. |
fake | boolean | |
submittedAt | string (date-time) or null | |
approvedAt | string (date-time) or null | |
lastCheckedAt | string (date-time) or null | |
otpSentAt | string (date-time) or null | Sole proprietor: when the confirmation text went to the owner's mobile (reply YES within 24 hours). |
textingNumber | string or null | The SKUFlow texting number being registered. |
details | object or null | What was submitted. |
details.brandType | enum | STANDARD for a business with an EIN; SOLE_PROPRIETOR without one (the owner confirms by text; one number). One of STANDARD, SOLE_PROPRIETOR. Default STANDARD. |
details.legalName | string | The legal business name exactly as on the IRS EIN letter (CP 575 / 147C); a sole proprietor's business or full name. Up to 255 characters. |
details.businessType | enum | One of Sole Proprietorship, Partnership, Limited Liability Corporation, Co-operative, Non-profit Corporation, Corporation. |
details.industry | enum | One of CONSTRUCTION, PROFESSIONAL_SERVICES, REAL_ESTATE, RETAIL, AUTOMOTIVE, ENERGY, HEALTHCARE, TRANSPORTATION. Default CONSTRUCTION. |
details.ein | string | The business's EIN (US tax id); required for STANDARD, empty for SOLE_PROPRIETOR. Default ``. |
details.companyType | enum | One of private, public, non-profit. Default private. |
details.websiteUrl | string (uri) | Up to 500 characters. |
details.privacyUrl | string (uri) | The public privacy policy (must say mobile numbers are not shared for marketing). Up to 2048 characters. |
details.termsUrl | string (uri) | The public terms with the SMS program details. Up to 2048 characters. |
details.street | string | Up to 200 characters. |
details.city | string | Up to 100 characters. |
details.region | string | Two-letter US state. Up to 2 characters. |
details.postalCode | string | |
details.representative | object | |
details.representative.firstName | string | Up to 100 characters. |
details.representative.lastName | string | Up to 100 characters. |
details.representative.email | string (email) | |
details.representative.phone | string | |
details.representative.title | string | Business title, e.g. Owner. Up to 100 characters. |
details.representative.jobPosition | enum | One of Director, GM, VP, CEO, CFO, General Counsel, Other. Default Director. |
details.useCase | enum | One of CUSTOMER_CARE, ACCOUNT_NOTIFICATION, MIXED, MARKETING. Default MIXED. |
details.description | string | Up to 1024 characters. |
details.messageFlow | string | Up to 2048 characters. |
details.sampleMessages | array of string | Up to 5 items. |
details.hasEmbeddedLinks | boolean | Default true. |
details.hasEmbeddedPhone | boolean | Default true. |
defaults | object | Suggestions from the business's profile, website and the signed-in person for the form. |
defaults.brandType | enum | One of STANDARD, SOLE_PROPRIETOR. |
defaults.legalName | string | |
defaults.businessType | enum | One of Sole Proprietorship, Partnership, Limited Liability Corporation, Co-operative, Non-profit Corporation, Corporation. |
defaults.websiteUrl | string | |
defaults.privacyUrl | string | |
defaults.termsUrl | string | |
defaults.optInUrl | string | The public page with the texting consent checkbox. |
defaults.street | string | |
defaults.city | string | |
defaults.region | string | |
defaults.postalCode | string | |
defaults.representative | object | |
defaults.representative.firstName | string | |
defaults.representative.lastName | string | |
defaults.representative.email | string | |
defaults.representative.phone | string | |
defaults.description | string | |
defaults.messageFlow | string | |
defaults.sampleMessages | array of string |
Register for A2P 10DLC
POST /organizations/{organizationId}/telephony/a2p
Money, sends data out: submits the business (legal name, EIN, address, website, an authorized representative) and its texting campaign (use case, description, opt-in flow, sample messages) to Twilio and The Campaign Registry from the business's SKUFlow sub-account. Twilio's brand and campaign fees are billed at cost + 20%. brandType STANDARD needs the EIN; SOLE_PROPRIETOR (no EIN) registers the owner, who then confirms by replying YES to a text (OTP_PENDING; one number, lower volume). Needs a SKUFlow texting number first, and refused with 400 and data.items while GET /telephony/a2p/readiness has a failure (call it first). Approval takes days: the status updates by itself (GET /telephony/a2p). A FAILED registration can be corrected and submitted again: issues name the fields Twilio refused; a failed campaign under an approved brand is replaced (a new campaign vetting fee).
| Permission | channels.manage (Owner, Admin) |
| Risk | sensitive, OAuth scope skuflow.sensitive. Sensitive: moves money, deletes, sends or shows something to a customer, or grants or revokes access. |
| MCP tool | telephony_submitA2p (toolset settings) |
| Approval | Over MCP, this tool asks for your OK first (in the AI app when it supports it, otherwise in SKUFlow). See Approvals. |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
brandType | enum | No | STANDARD for a business with an EIN; SOLE_PROPRIETOR without one (the owner confirms by text; one number). One of STANDARD, SOLE_PROPRIETOR. Default STANDARD. |
legalName | string | Yes | The legal business name exactly as on the IRS EIN letter (CP 575 / 147C); a sole proprietor's business or full name. Up to 255 characters. |
businessType | enum | Yes | One of Sole Proprietorship, Partnership, Limited Liability Corporation, Co-operative, Non-profit Corporation, Corporation. |
industry | enum | No | One of CONSTRUCTION, PROFESSIONAL_SERVICES, REAL_ESTATE, RETAIL, AUTOMOTIVE, ENERGY, HEALTHCARE, TRANSPORTATION. Default CONSTRUCTION. |
ein | string | No | The business's EIN (US tax id); required for STANDARD, empty for SOLE_PROPRIETOR. Default ``. |
companyType | enum | No | One of private, public, non-profit. Default private. |
websiteUrl | string | Yes | |
privacyUrl | string | No | The public privacy policy (must say mobile numbers are not shared for marketing). |
termsUrl | string | No | The public terms with the SMS program details. |
street | string | Yes | Up to 200 characters. |
city | string | Yes | Up to 100 characters. |
region | string | Yes | Two-letter US state. Up to 2 characters. |
postalCode | string | Yes | |
representative | object | Yes | |
representative.firstName | string | Yes | Up to 100 characters. |
representative.lastName | string | Yes | Up to 100 characters. |
representative.email | string (email) | Yes | |
representative.phone | string | Yes | |
representative.title | string | Yes | Business title, e.g. Owner. Up to 100 characters. |
representative.jobPosition | enum | No | One of Director, GM, VP, CEO, CFO, General Counsel, Other. Default Director. |
useCase | enum | No | One of CUSTOMER_CARE, ACCOUNT_NOTIFICATION, MIXED, MARKETING. Default MIXED. |
description | string | Yes | Up to 1024 characters. |
messageFlow | string | Yes | Up to 2048 characters. |
sampleMessages | array of string | Yes | Up to 5 items. |
hasEmbeddedLinks | boolean | No | Default true. |
hasEmbeddedPhone | boolean | No | Default true. |
Example
curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/telephony/a2p" \
-H "Authorization: Bearer $SKUFLOW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"legalName":"string","businessType":"Sole Proprietorship","websiteUrl":"https://example.com","street":"string","city":"string","region":"string","postalCode":"string","representative":{"firstName":"string","lastName":"string","email":"dana@example.com","phone":"+15555550123","title":"string"},"description":"string","messageFlow":"string","sampleMessages":["string"]}'Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
status | enum | One of NOT_STARTED, PROFILE_SUBMITTED, BRAND_PENDING, OTP_PENDING, BRAND_APPROVED, CAMPAIGN_PENDING, APPROVED, FAILED. |
brandType | enum | One of STANDARD, SOLE_PROPRIETOR. |
brandStatus | string or null | |
identityStatus | string or null | Twilio's brand identity check: SELF_DECLARED, UNVERIFIED, VERIFIED, VETTED_VERIFIED. |
customerProfileStatus | string or null | Trust Hub customer profile status. |
trustProductStatus | string or null | Trust Hub A2P bundle status. |
campaignStatus | string or null | |
messagingServiceSid | string or null | |
failureReason | string or null | |
issues | array of object | Why it was refused, per field (empty unless FAILED). |
issues[].source | enum | Which step refused it. One of profile, trust, brand, otp, campaign, submit. |
issues[].code | integer or null | Twilio's error code (twilio.com/docs/api/errors/{code}). |
issues[].field | string or null | The registration field to change (e.g. ein, messageFlow, sampleMessages.0). |
issues[].message | string | What to fix, in plain English. |
issues[].detail | string or null | Twilio's own words. |
fake | boolean | |
submittedAt | string (date-time) or null | |
approvedAt | string (date-time) or null | |
lastCheckedAt | string (date-time) or null | |
otpSentAt | string (date-time) or null | Sole proprietor: when the confirmation text went to the owner's mobile (reply YES within 24 hours). |
textingNumber | string or null | The SKUFlow texting number being registered. |
details | object or null | What was submitted. |
details.brandType | enum | STANDARD for a business with an EIN; SOLE_PROPRIETOR without one (the owner confirms by text; one number). One of STANDARD, SOLE_PROPRIETOR. Default STANDARD. |
details.legalName | string | The legal business name exactly as on the IRS EIN letter (CP 575 / 147C); a sole proprietor's business or full name. Up to 255 characters. |
details.businessType | enum | One of Sole Proprietorship, Partnership, Limited Liability Corporation, Co-operative, Non-profit Corporation, Corporation. |
details.industry | enum | One of CONSTRUCTION, PROFESSIONAL_SERVICES, REAL_ESTATE, RETAIL, AUTOMOTIVE, ENERGY, HEALTHCARE, TRANSPORTATION. Default CONSTRUCTION. |
details.ein | string | The business's EIN (US tax id); required for STANDARD, empty for SOLE_PROPRIETOR. Default ``. |
details.companyType | enum | One of private, public, non-profit. Default private. |
details.websiteUrl | string (uri) | Up to 500 characters. |
details.privacyUrl | string (uri) | The public privacy policy (must say mobile numbers are not shared for marketing). Up to 2048 characters. |
details.termsUrl | string (uri) | The public terms with the SMS program details. Up to 2048 characters. |
details.street | string | Up to 200 characters. |
details.city | string | Up to 100 characters. |
details.region | string | Two-letter US state. Up to 2 characters. |
details.postalCode | string | |
details.representative | object | |
details.representative.firstName | string | Up to 100 characters. |
details.representative.lastName | string | Up to 100 characters. |
details.representative.email | string (email) | |
details.representative.phone | string | |
details.representative.title | string | Business title, e.g. Owner. Up to 100 characters. |
details.representative.jobPosition | enum | One of Director, GM, VP, CEO, CFO, General Counsel, Other. Default Director. |
details.useCase | enum | One of CUSTOMER_CARE, ACCOUNT_NOTIFICATION, MIXED, MARKETING. Default MIXED. |
details.description | string | Up to 1024 characters. |
details.messageFlow | string | Up to 2048 characters. |
details.sampleMessages | array of string | Up to 5 items. |
details.hasEmbeddedLinks | boolean | Default true. |
details.hasEmbeddedPhone | boolean | Default true. |
defaults | object | Suggestions from the business's profile, website and the signed-in person for the form. |
defaults.brandType | enum | One of STANDARD, SOLE_PROPRIETOR. |
defaults.legalName | string | |
defaults.businessType | enum | One of Sole Proprietorship, Partnership, Limited Liability Corporation, Co-operative, Non-profit Corporation, Corporation. |
defaults.websiteUrl | string | |
defaults.privacyUrl | string | |
defaults.termsUrl | string | |
defaults.optInUrl | string | The public page with the texting consent checkbox. |
defaults.street | string | |
defaults.city | string | |
defaults.region | string | |
defaults.postalCode | string | |
defaults.representative | object | |
defaults.representative.firstName | string | |
defaults.representative.lastName | string | |
defaults.representative.email | string | |
defaults.representative.phone | string | |
defaults.description | string | |
defaults.messageFlow | string | |
defaults.sampleMessages | array of string |
Check an A2P registration before submitting
GET /organizations/{organizationId}/telephony/a2p/readiness
Runs the checks that keep an A2P 10DLC registration from being rejected, without sending anything: texting number, legal name vs business type (match the IRS EIN letter), EIN, physical address, website / privacy / terms open publicly (fetched now), the privacy policy's SMS clause and the booking page's consent checkbox, the representative, the campaign text and samples (business name, STOP), lengths and restricted content. Checks what was submitted, else the suggestions; websiteUrl, privacyUrl, termsUrl check other addresses. Each item is pass, warn or fail; POST /telephony/a2p is refused while any fails. Read-only.
| Permission | channels.manage (Owner, Admin) |
| Risk | read, OAuth scope skuflow.read. Read: reads only. |
| MCP tool | telephony_a2pReadiness (toolset settings) |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
websiteUrl | query | string | No | |
privacyUrl | query | string | No | |
termsUrl | query | string | No |
Example
curl "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/telephony/a2p/readiness" \
-H "Authorization: Bearer $SKUFLOW_API_KEY"Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
ready | boolean | No failures: the registration may be submitted. |
items | array of object | |
items[].key | string | |
items[].status | enum | fail blocks the submission; warn is advice. One of pass, warn, fail. |
items[].message | string | |
items[].field | string | The registration field to fix. |
items[].fix | enum | Fixed elsewhere: website (Website → legal pages, request form checkbox) or texting (Settings → Messaging number). One of website, texting. |
facts | object | What the server checked; the form re-runs the same rules on what is typed. |
facts.textingNumber | string or null | |
facts.compliance | object or null | |
facts.compliance.businessName | string | |
facts.compliance.siteUrl | string or null | |
facts.compliance.sitePublished | boolean | |
facts.compliance.optInUrl | string | |
facts.compliance.optInHasConsent | boolean | |
facts.compliance.privacyHasSmsClause | boolean | |
facts.reachable | object | Whether each URL opened (null: not checked). |
Resend the sole proprietor confirmation text
POST /organizations/{organizationId}/telephony/a2p/otp
Sends a text: a sole proprietor's brand is confirmed by its owner replying YES to a text Twilio sends to the representative's mobile (valid 24 hours). This asks Twilio to send it again; only while the status is OTP_PENDING, at most every five minutes.
| Permission | channels.manage (Owner, Admin) |
| Risk | sensitive, OAuth scope skuflow.sensitive. Sensitive: moves money, deletes, sends or shows something to a customer, or grants or revokes access. |
| MCP tool | telephony_resendA2pOtp (toolset settings) |
| Approval | Over MCP, this tool asks for your OK first (in the AI app when it supports it, otherwise in SKUFlow). See Approvals. |
Example
curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/telephony/a2p/otp" \
-H "Authorization: Bearer $SKUFLOW_API_KEY"Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
status | enum | One of NOT_STARTED, PROFILE_SUBMITTED, BRAND_PENDING, OTP_PENDING, BRAND_APPROVED, CAMPAIGN_PENDING, APPROVED, FAILED. |
brandType | enum | One of STANDARD, SOLE_PROPRIETOR. |
brandStatus | string or null | |
identityStatus | string or null | Twilio's brand identity check: SELF_DECLARED, UNVERIFIED, VERIFIED, VETTED_VERIFIED. |
customerProfileStatus | string or null | Trust Hub customer profile status. |
trustProductStatus | string or null | Trust Hub A2P bundle status. |
campaignStatus | string or null | |
messagingServiceSid | string or null | |
failureReason | string or null | |
issues | array of object | Why it was refused, per field (empty unless FAILED). |
issues[].source | enum | Which step refused it. One of profile, trust, brand, otp, campaign, submit. |
issues[].code | integer or null | Twilio's error code (twilio.com/docs/api/errors/{code}). |
issues[].field | string or null | The registration field to change (e.g. ein, messageFlow, sampleMessages.0). |
issues[].message | string | What to fix, in plain English. |
issues[].detail | string or null | Twilio's own words. |
fake | boolean | |
submittedAt | string (date-time) or null | |
approvedAt | string (date-time) or null | |
lastCheckedAt | string (date-time) or null | |
otpSentAt | string (date-time) or null | Sole proprietor: when the confirmation text went to the owner's mobile (reply YES within 24 hours). |
textingNumber | string or null | The SKUFlow texting number being registered. |
details | object or null | What was submitted. |
details.brandType | enum | STANDARD for a business with an EIN; SOLE_PROPRIETOR without one (the owner confirms by text; one number). One of STANDARD, SOLE_PROPRIETOR. Default STANDARD. |
details.legalName | string | The legal business name exactly as on the IRS EIN letter (CP 575 / 147C); a sole proprietor's business or full name. Up to 255 characters. |
details.businessType | enum | One of Sole Proprietorship, Partnership, Limited Liability Corporation, Co-operative, Non-profit Corporation, Corporation. |
details.industry | enum | One of CONSTRUCTION, PROFESSIONAL_SERVICES, REAL_ESTATE, RETAIL, AUTOMOTIVE, ENERGY, HEALTHCARE, TRANSPORTATION. Default CONSTRUCTION. |
details.ein | string | The business's EIN (US tax id); required for STANDARD, empty for SOLE_PROPRIETOR. Default ``. |
details.companyType | enum | One of private, public, non-profit. Default private. |
details.websiteUrl | string (uri) | Up to 500 characters. |
details.privacyUrl | string (uri) | The public privacy policy (must say mobile numbers are not shared for marketing). Up to 2048 characters. |
details.termsUrl | string (uri) | The public terms with the SMS program details. Up to 2048 characters. |
details.street | string | Up to 200 characters. |
details.city | string | Up to 100 characters. |
details.region | string | Two-letter US state. Up to 2 characters. |
details.postalCode | string | |
details.representative | object | |
details.representative.firstName | string | Up to 100 characters. |
details.representative.lastName | string | Up to 100 characters. |
details.representative.email | string (email) | |
details.representative.phone | string | |
details.representative.title | string | Business title, e.g. Owner. Up to 100 characters. |
details.representative.jobPosition | enum | One of Director, GM, VP, CEO, CFO, General Counsel, Other. Default Director. |
details.useCase | enum | One of CUSTOMER_CARE, ACCOUNT_NOTIFICATION, MIXED, MARKETING. Default MIXED. |
details.description | string | Up to 1024 characters. |
details.messageFlow | string | Up to 2048 characters. |
details.sampleMessages | array of string | Up to 5 items. |
details.hasEmbeddedLinks | boolean | Default true. |
details.hasEmbeddedPhone | boolean | Default true. |
defaults | object | Suggestions from the business's profile, website and the signed-in person for the form. |
defaults.brandType | enum | One of STANDARD, SOLE_PROPRIETOR. |
defaults.legalName | string | |
defaults.businessType | enum | One of Sole Proprietorship, Partnership, Limited Liability Corporation, Co-operative, Non-profit Corporation, Corporation. |
defaults.websiteUrl | string | |
defaults.privacyUrl | string | |
defaults.termsUrl | string | |
defaults.optInUrl | string | The public page with the texting consent checkbox. |
defaults.street | string | |
defaults.city | string | |
defaults.region | string | |
defaults.postalCode | string | |
defaults.representative | object | |
defaults.representative.firstName | string | |
defaults.representative.lastName | string | |
defaults.representative.email | string | |
defaults.representative.phone | string | |
defaults.description | string | |
defaults.messageFlow | string | |
defaults.sampleMessages | array of string |
Check the A2P status now
POST /organizations/{organizationId}/telephony/a2p/refresh
Asks Twilio for the brand or campaign status now instead of waiting for the worker; once the brand is approved this creates the Messaging Service in the sub-account, adds the texting number and submits the campaign.
| Permission | channels.manage (Owner, Admin) |
| Risk | write, OAuth scope skuflow.write. Write: creates or changes records inside the business; nothing leaves it. |
| MCP tool | telephony_refreshA2p (toolset settings) |
Example
curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/telephony/a2p/refresh" \
-H "Authorization: Bearer $SKUFLOW_API_KEY"Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
status | enum | One of NOT_STARTED, PROFILE_SUBMITTED, BRAND_PENDING, OTP_PENDING, BRAND_APPROVED, CAMPAIGN_PENDING, APPROVED, FAILED. |
brandType | enum | One of STANDARD, SOLE_PROPRIETOR. |
brandStatus | string or null | |
identityStatus | string or null | Twilio's brand identity check: SELF_DECLARED, UNVERIFIED, VERIFIED, VETTED_VERIFIED. |
customerProfileStatus | string or null | Trust Hub customer profile status. |
trustProductStatus | string or null | Trust Hub A2P bundle status. |
campaignStatus | string or null | |
messagingServiceSid | string or null | |
failureReason | string or null | |
issues | array of object | Why it was refused, per field (empty unless FAILED). |
issues[].source | enum | Which step refused it. One of profile, trust, brand, otp, campaign, submit. |
issues[].code | integer or null | Twilio's error code (twilio.com/docs/api/errors/{code}). |
issues[].field | string or null | The registration field to change (e.g. ein, messageFlow, sampleMessages.0). |
issues[].message | string | What to fix, in plain English. |
issues[].detail | string or null | Twilio's own words. |
fake | boolean | |
submittedAt | string (date-time) or null | |
approvedAt | string (date-time) or null | |
lastCheckedAt | string (date-time) or null | |
otpSentAt | string (date-time) or null | Sole proprietor: when the confirmation text went to the owner's mobile (reply YES within 24 hours). |
textingNumber | string or null | The SKUFlow texting number being registered. |
details | object or null | What was submitted. |
details.brandType | enum | STANDARD for a business with an EIN; SOLE_PROPRIETOR without one (the owner confirms by text; one number). One of STANDARD, SOLE_PROPRIETOR. Default STANDARD. |
details.legalName | string | The legal business name exactly as on the IRS EIN letter (CP 575 / 147C); a sole proprietor's business or full name. Up to 255 characters. |
details.businessType | enum | One of Sole Proprietorship, Partnership, Limited Liability Corporation, Co-operative, Non-profit Corporation, Corporation. |
details.industry | enum | One of CONSTRUCTION, PROFESSIONAL_SERVICES, REAL_ESTATE, RETAIL, AUTOMOTIVE, ENERGY, HEALTHCARE, TRANSPORTATION. Default CONSTRUCTION. |
details.ein | string | The business's EIN (US tax id); required for STANDARD, empty for SOLE_PROPRIETOR. Default ``. |
details.companyType | enum | One of private, public, non-profit. Default private. |
details.websiteUrl | string (uri) | Up to 500 characters. |
details.privacyUrl | string (uri) | The public privacy policy (must say mobile numbers are not shared for marketing). Up to 2048 characters. |
details.termsUrl | string (uri) | The public terms with the SMS program details. Up to 2048 characters. |
details.street | string | Up to 200 characters. |
details.city | string | Up to 100 characters. |
details.region | string | Two-letter US state. Up to 2 characters. |
details.postalCode | string | |
details.representative | object | |
details.representative.firstName | string | Up to 100 characters. |
details.representative.lastName | string | Up to 100 characters. |
details.representative.email | string (email) | |
details.representative.phone | string | |
details.representative.title | string | Business title, e.g. Owner. Up to 100 characters. |
details.representative.jobPosition | enum | One of Director, GM, VP, CEO, CFO, General Counsel, Other. Default Director. |
details.useCase | enum | One of CUSTOMER_CARE, ACCOUNT_NOTIFICATION, MIXED, MARKETING. Default MIXED. |
details.description | string | Up to 1024 characters. |
details.messageFlow | string | Up to 2048 characters. |
details.sampleMessages | array of string | Up to 5 items. |
details.hasEmbeddedLinks | boolean | Default true. |
details.hasEmbeddedPhone | boolean | Default true. |
defaults | object | Suggestions from the business's profile, website and the signed-in person for the form. |
defaults.brandType | enum | One of STANDARD, SOLE_PROPRIETOR. |
defaults.legalName | string | |
defaults.businessType | enum | One of Sole Proprietorship, Partnership, Limited Liability Corporation, Co-operative, Non-profit Corporation, Corporation. |
defaults.websiteUrl | string | |
defaults.privacyUrl | string | |
defaults.termsUrl | string | |
defaults.optInUrl | string | The public page with the texting consent checkbox. |
defaults.street | string | |
defaults.city | string | |
defaults.region | string | |
defaults.postalCode | string | |
defaults.representative | object | |
defaults.representative.firstName | string | |
defaults.representative.lastName | string | |
defaults.representative.email | string | |
defaults.representative.phone | string | |
defaults.description | string | |
defaults.messageFlow | string | |
defaults.sampleMessages | array of string |
Telephony usage this month
GET /organizations/{organizationId}/telephony/usage
This month's telephony from the business's SKUFlow sub-account per category (voice minutes, numbers, texts, recordings, transcriptions, registration fees, other): counts, what is billed so far and the estimate to date at Twilio's cost × 1.2. Texts are shown but billed by the plan's text allowance. Read-only.
| Permission | phone.manage (Owner, Admin) |
| Risk | read, OAuth scope skuflow.read. Read: reads only. |
| MCP tool | telephony_usage (toolset settings) |
Example
curl "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/telephony/usage" \
-H "Authorization: Bearer $SKUFLOW_API_KEY"Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
month | string | First day of the month, YYYY-MM-DD (UTC). |
markup | number | Twilio's cost × this is the charge (1.2 = cost + 20%). |
billedThrough | string or null | Last UTC day billed from Twilio's Usage Records. |
available | boolean | False until the business has a SKUFlow sub-account. |
lines | array of object | |
lines[].category | enum | One of voice, numbers, texts, recordings, transcriptions, registration, other. |
lines[].count | number | |
lines[].usage | number | |
lines[].usageUnit | string or null | |
lines[].billable | boolean | False for texts: the plan's text allowance and overage bill them. |
lines[].billedCents | integer | Recorded for billing (settled days). |
lines[].estimatedCents | integer | Month to date, settled plus not yet settled. |
totalCents | integer | |
billedCents | integer |
Run telephony jobs now
POST /organizations/{organizationId}/telephony/run
Run this business's telephony jobs now instead of waiting for the worker: reconcile the sub-account with the SKUFlow subscription (suspend, reactivate, close, scheduled number releases), bill settled Twilio usage (each account × day × category once) and check the A2P registration. now is test-only (refused in production).
| Permission | phone.manage (Owner, Admin) |
| Risk | write, OAuth scope skuflow.write. Write: creates or changes records inside the business; nothing leaves it. |
| MCP tool | telephony_run (toolset settings) |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
now | string (date-time) | No |
Example
curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/telephony/run" \
-H "Authorization: Bearer $SKUFLOW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"now":"2026-11-03T15:00:00Z"}'Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
lifecycle | object | |
lifecycle.checked | integer | |
lifecycle.suspended | integer | |
lifecycle.reactivated | integer | |
lifecycle.closed | integer | |
lifecycle.numbersReleased | integer | |
lifecycle.numbersScheduled | integer | |
usage | object | |
usage.accounts | integer | |
usage.days | integer | |
usage.rows | integer | |
usage.recorded | integer | |
usage.simulated | integer | |
usage.failed | integer | |
a2p | object | |
a2p.checked | integer |