Skip to content

Regulatory Requirements

Fulfill regulatory requirements for phone number purchases in certain countries

View .md

Some phone numbers require regulatory information before they can be used: an address, an identity or business document, or text such as a business name. Which numbers do is decided per number by the carrier, not by a fixed list of countries, and the purchase checks it for the exact number you buy, before anything is charged.

Overview

To buy a number with regulatory requirements:

  1. Check requirements for the number you want to buy
  2. Create addresses for any address requirement
  3. Upload documents for any document requirement
  4. Purchase the number with its type, passing every requirement as regulatoryRequirements
  5. Wait for review: the number is yours immediately with regulatoryStatus: pending_review, and can send messages and place calls once it is approved
  6. Assign it to a sender, before or after approval

The information is kept for your project under the number's country and type. A later purchase in the same country and type may omit regulatoryRequirements, as long as what is kept still covers that number's requirements.

Checking Requirements

Before purchasing, check what requirements apply. Pass phoneNumber with a number from GET /v1/phone-numbers/available to get the requirements for that exact number, which is what the purchase checks. Encode its + as %2B. countryCode and type give the requirements for a country instead:

terminal
curl "https://api.zavu.dev/v1/phone-numbers/requirements?phoneNumber=%2B4930123456" \ -H "Authorization: Bearer $ZAVUDEV_API_KEY"

An empty items array means the number needs nothing: buy it normally. When the number's own requirements cannot be resolved, the list for its country and type is returned instead, and the purchase checks the same list. If the requirements cannot be retrieved at all, the API answers 502 with code requirements_unavailable instead of an empty list: retry rather than purchasing without them. For US and Canadian numbers a purchase does not wait on this lookup: they are sold as numbers without requirements.

The SDKs below take countryCode and type; they have no per-number variant yet:

const requirements = await zavu.phoneNumbers.requirements({ countryCode: "DE", type: "local", }); for (const req of requirements.items) { console.log("Requirement:", req.id); for (const type of req.requirementTypes) { console.log(" -", type.name, `(${type.type})`); console.log(" ", type.description); } }

Requirement Types

TypeDescription
addressAn address: create one and pass its id
documentAn identity or business document: upload one and pass its id
textualText (e.g. a business name): pass the text itself
actionAn instruction to follow; send no entry for it

Response

JSON
{ "items": [ { "id": "+4930123456", "countryCode": "DE", "phoneNumberType": "local", "action": "ordering", "requirementTypes": [ { "id": "8c5b1a2e-0f3d-4f5b-9a61-2c7e4d9b1f10", "name": "Address", "description": "An address within Germany", "type": "address" }, { "id": "3f9e2d41-7b6a-4c1e-8d52-9a0b1c2d3e4f", "name": "Identity Document", "description": "Government-issued ID", "type": "document" } ] } ] }

For a phoneNumber request, id is that phone number. For a country request it identifies the requirement group. acceptanceCriteria, when present, carries allowedValues on a phoneNumber request, and minLength, maxLength and allowedValues on a country request.

Creating Addresses

If an address requirement exists, create an address first:

const created = await zavu.addresses.create({ firstName: "John", lastName: "Doe", streetAddress: "Unter den Linden 77", locality: "Berlin", administrativeArea: "Berlin", postalCode: "10117", countryCode: "DE", }); console.log("Address ID:", created.address.id); console.log("Status:", created.address.status);

Address Fields

FieldTypeRequiredDescription
firstNamestringYesFirst name of the person the address is registered to
lastNamestringYesLast name of the person the address is registered to
businessNamestringNoBusiness name, for a business address. Defaults to the person's full name
streetAddressstringYesStreet address line 1
extendedAddressstringNoStreet address line 2 (apartment, suite, etc.)
localitystringYesCity or town
administrativeAreastringNoState, province, or region
postalCodestringYesPostal or ZIP code
countryCodestringYesTwo-letter ISO country code

Address Status

A new address is returned with status: pending and stays that way. You can use its id in a purchase right away, in the same project it was created in. Review happens on the purchase, not on the address: follow it with the number's regulatoryStatus. An address marked rejected is refused in a purchase.

Uploading Documents

If a document requirement exists, upload the required document:

// Step 1: Get upload URL const { uploadUrl } = await zavu.regulatoryDocuments.uploadURL(); // Step 2: Upload the file to the returned URL const uploadResponse = await fetch(uploadUrl, { method: "POST", headers: { "Content-Type": "image/jpeg" }, body: fileBuffer, }); const { storageId } = await uploadResponse.json(); // Step 3: Create document record with the storageId const created = await zavu.regulatoryDocuments.create({ name: "John Doe Passport", documentType: "passport", storageId: storageId, mimeType: "image/jpeg", fileSize: fileBuffer.byteLength, }); console.log("Document ID:", created.document.id); console.log("Status:", created.document.status);

Supported Document Types

TypeDescription
passportGovernment-issued passport
national_idNational identity card
drivers_licenseDriver's license
utility_billUtility bill (for proof of address)
tax_idTax identification document
business_registrationBusiness registration certificate
proof_of_addressBank statement or official letter
otherOther document type

File Requirements

The API does not check the file's format or size; the dashboard uploader accepts the following, so stay within it:

  • Formats: JPEG, PNG, or PDF
  • Max size: 10MB
  • Quality: Clear, readable scan or photo
  • Validity: Document must not be expired

Document Status

A new document is returned with status: uploaded and stays that way. You can use its id in a purchase right away, in the project it was uploaded to. Review happens on the purchase, not on the document: follow it with the number's regulatoryStatus. A document marked rejected is refused in a purchase.

Purchasing with Requirements

Pass one entry per requirement except action ones: requirementType is the requirementTypes[].id from the requirements response, and fieldValue is the address id, the document id, or the text. type is required alongside, the type you searched the number under.

Every required id must be present, once, no unknown id may be sent, and addresses and documents must belong to the project making the purchase and must not be rejected. Otherwise the purchase is refused with 400 invalid_request, naming the requirement, before anything is charged. The same happens if an address or document cannot be registered for review.

cURL
curl -X POST https://api.zavu.dev/v1/phone-numbers \ -H "Authorization: Bearer $ZAVUDEV_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "phoneNumber": "+4930123456", "name": "Germany Line", "type": "local", "regulatoryRequirements": [ { "requirementType": "8c5b1a2e-0f3d-4f5b-9a61-2c7e4d9b1f10", "fieldValue": "<address id>" }, { "requirementType": "3f9e2d41-7b6a-4c1e-8d52-9a0b1c2d3e4f", "fieldValue": "<document id>" } ] }'

The response is the purchased number. It is billed from purchase, and cannot send messages or place calls until review approves it:

JSON
{ "phoneNumber": { "id": "pn_abc123", "phoneNumber": "+4930123456", "status": "active", "regulatoryStatus": "pending_review" } }

The status is re-checked every 6 hours. Poll GET /v1/phone-numbers/{phoneNumberId} until regulatoryStatus is approved or rejected.

Assigning a Sender

Assign the number to a sender to use it, before or after approval:

cURL
curl -X PATCH https://api.zavu.dev/v1/phone-numbers/pn_abc123 \ -H "Authorization: Bearer $ZAVUDEV_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "senderId": "snd_abc123" }'

Assigned while pending_review, the number is recorded on the sender and connected when it is approved; if that connection fails it is retried until it succeeds. A sender created over the API is set up for SMS as part of the assignment. A rejected number cannot be assigned: the call answers 400. A number that stays pending_review for long may be waiting on information the API cannot supply: contact support.

Reusing Submitted Information

If the number needs regulatory information and the request carries none, the purchase reuses what your project submitted before for the same country and type, but only when it still covers every requirement of the new number and every address and document in it belongs to the project. Otherwise it is refused with 400 regulatory_compliance_required, listing the missing requirements in details.missingRequirements, and nothing is charged.

Managing Addresses

List Addresses

const result = await zavu.addresses.list(); for (const address of result.items) { console.log(address.id, address.streetAddress, address.status); }

Delete Address

await zavu.addresses.delete("addr_abc123");

Managing Documents

List Documents

const result = await zavu.regulatoryDocuments.list(); for (const doc of result.items) { console.log(doc.id, doc.name, doc.status); }

Delete Document

await zavu.regulatoryDocuments.delete("doc_xyz789");

Country-Specific Requirements

Requirements differ by country and number type, and change with regulation. The requirements endpoint is the source of truth: query it for the number you are about to buy rather than relying on a fixed list.

Best Practices

Prepare Documents First

Create addresses and upload documents before the purchase call, so it carries every requirement.

Follow the Review

A regulated number is billed from purchase but usable only once regulatoryStatus is approved.

Keep Documents Current

Ensure documents are not expired and information is up to date.

Check Requirements Early

Query requirements during your planning phase to avoid purchase delays.

Error Handling

StatusCodeDescription
400regulatory_compliance_requiredThe number needs regulatory information and none was provided or reusable. details.missingRequirements lists what to send
400invalid_requestMalformed request, a missing, unknown or repeated requirement id, an address or document from another project or rejected in review, one that could not be registered for review, type missing with regulatoryRequirements, or requirements that cannot be looked up for this input
400number_unavailableThe number is no longer available, or is not listed under the type sent
502requirements_unavailableThe requirements lookup failed. Retry; it does not mean nothing is required. A purchase refused this way is not charged. A purchase of a US or Canadian number does not return it, because it goes ahead as a number without requirements; this endpoint returns it for any country

Next Steps