> ## Documentation Index
> Fetch the complete documentation index at: https://docs.zavu.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Regulatory Requirements

> Fulfill regulatory requirements for phone number purchases in certain countries

Some countries require additional documentation before phone numbers can be activated for messaging. This includes identity verification documents, proof of address, or business registration papers.

## Overview

When purchasing phone numbers in countries with regulatory requirements, you'll need to:

1. **Check requirements** for the specific country and number type
2. **Create addresses** if address verification is required
3. **Upload documents** if identity verification is required
4. **Submit requirements** along with your purchase request

<Info>
  Phone numbers in the US and Canada typically don't require additional documentation. Requirements are most common in European, Latin American, and Asian countries.
</Info>

## Checking Requirements

Before purchasing, check what requirements apply:

<CodeGroup>
  ```typescript TypeScript theme={null}
  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);
    }
  }
  ```

  ```python Python theme={null}
  requirements = zavu.phone_numbers.requirements(
      country_code="DE",
      type="local"
  )

  for req in requirements.items:
      print("Requirement:", req.id)
      for type in req.requirement_types:
          print(f"  - {type.name} ({type.type})")
          print(f"    {type.description}")
  ```

  ```ruby Ruby theme={null}
  requirements = client.phone_numbers.requirements(
    country_code: "DE",
    type: "local"
  )

  requirements.items.each do |req|
    puts "Requirement: #{req.id}"
    req.requirement_types.each do |type|
      puts "  - #{type.name} (#{type.type})"
      puts "    #{type.description}"
    end
  end
  ```

  ```go Go theme={null}
  requirements, _ := client.PhoneNumbers.Requirements(context.TODO(), zavudev.PhoneNumberRequirementsParams{
  	CountryCode: zavudev.String("DE"),
  	Type:        zavudev.String("local"),
  })

  for _, req := range requirements.Items {
  	fmt.Println("Requirement:", req.ID)
  	for _, t := range req.RequirementTypes {
  		fmt.Printf("  - %s (%s)\n", t.Name, t.Type)
  		fmt.Printf("    %s\n", t.Description)
  	}
  }
  ```

  ```php PHP theme={null}
  $requirements = $client->phoneNumbers->requirements([
      'countryCode' => 'DE',
      'type' => 'local',
  ]);

  foreach ($requirements->items as $req) {
      echo "Requirement: {$req->id}\n";
      foreach ($req->requirementTypes as $type) {
          echo "  - {$type->name} ({$type->type})\n";
          echo "    {$type->description}\n";
      }
  }
  ```

  ```bash cURL theme={null}
  curl "https://api.zavu.dev/v1/phone-numbers/requirements?countryCode=DE&type=local" \
    -H "Authorization: Bearer $ZAVU_API_KEY"
  ```
</CodeGroup>

### Requirement Types

| Type       | Description                                            |
| ---------- | ------------------------------------------------------ |
| `address`  | A verified physical address is required                |
| `document` | Identity or business document verification is required |
| `textual`  | Text information (e.g., business name) is required     |

### Response

```json theme={null}
{
  "items": [
    {
      "id": "req_12345",
      "countryCode": "DE",
      "phoneNumberType": "local",
      "action": "ordering",
      "requirementTypes": [
        {
          "id": "rt_address_de",
          "name": "German Address",
          "description": "A verified address within Germany",
          "type": "address",
          "acceptanceCriteria": {
            "address_countries": ["DE"]
          }
        },
        {
          "id": "rt_id_document",
          "name": "Identity Document",
          "description": "Government-issued ID (passport, national ID)",
          "type": "document",
          "acceptanceCriteria": {
            "document_types": ["passport", "national_id", "drivers_license"]
          }
        }
      ]
    }
  ]
}
```

## Creating Addresses

If an address requirement exists, create an address first:

<CodeGroup>
  ```typescript TypeScript theme={null}
  const address = 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:", address.id);
  console.log("Status:", address.status);
  ```

  ```python Python theme={null}
  address = zavu.addresses.create(
      first_name="John",
      last_name="Doe",
      street_address="Unter den Linden 77",
      locality="Berlin",
      administrative_area="Berlin",
      postal_code="10117",
      country_code="DE"
  )

  print("Address ID:", address.id)
  print("Status:", address.status)
  ```

  ```ruby Ruby theme={null}
  address = client.addresses.create(
    first_name: "John",
    last_name: "Doe",
    street_address: "Unter den Linden 77",
    locality: "Berlin",
    administrative_area: "Berlin",
    postal_code: "10117",
    country_code: "DE"
  )

  puts "Address ID: #{address.id}"
  puts "Status: #{address.status}"
  ```

  ```go Go theme={null}
  address, _ := client.Addresses.Create(context.TODO(), zavudev.AddressCreateParams{
  	FirstName:          zavudev.String("John"),
  	LastName:           zavudev.String("Doe"),
  	StreetAddress:      zavudev.String("Unter den Linden 77"),
  	Locality:           zavudev.String("Berlin"),
  	AdministrativeArea: zavudev.String("Berlin"),
  	PostalCode:         zavudev.String("10117"),
  	CountryCode:        zavudev.String("DE"),
  })

  fmt.Println("Address ID:", address.ID)
  fmt.Println("Status:", address.Status)
  ```

  ```php PHP theme={null}
  $address = $client->addresses->create([
      'firstName' => 'John',
      'lastName' => 'Doe',
      'streetAddress' => 'Unter den Linden 77',
      'locality' => 'Berlin',
      'administrativeArea' => 'Berlin',
      'postalCode' => '10117',
      'countryCode' => 'DE',
  ]);

  echo "Address ID: {$address->id}\n";
  echo "Status: {$address->status}\n";
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.zavu.dev/v1/addresses \
    -H "Authorization: Bearer $ZAVU_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "firstName": "John",
      "lastName": "Doe",
      "streetAddress": "Unter den Linden 77",
      "locality": "Berlin",
      "administrativeArea": "Berlin",
      "postalCode": "10117",
      "countryCode": "DE"
    }'
  ```
</CodeGroup>

### Address Fields

| Field                | Type   | Required | Description                                    |
| -------------------- | ------ | -------- | ---------------------------------------------- |
| `firstName`          | string | No       | First name of the individual                   |
| `lastName`           | string | No       | Last name of the individual                    |
| `businessName`       | string | No       | Business name (for business addresses)         |
| `streetAddress`      | string | Yes      | Street address line 1                          |
| `extendedAddress`    | string | No       | Street address line 2 (apartment, suite, etc.) |
| `locality`           | string | Yes      | City or town                                   |
| `administrativeArea` | string | No       | State, province, or region                     |
| `postalCode`         | string | Yes      | Postal or ZIP code                             |
| `countryCode`        | string | Yes      | Two-letter ISO country code                    |

### Address Statuses

| Status     | Description                                 |
| ---------- | ------------------------------------------- |
| `pending`  | Address submitted and awaiting verification |
| `verified` | Address has been verified and can be used   |
| `rejected` | Address verification failed                 |

<Info>
  Address verification typically completes within a few minutes but may take up to 24 hours in some cases.
</Info>

## Uploading Documents

If a document requirement exists, upload the required document:

<CodeGroup>
  ```typescript TypeScript theme={null}
  // Step 1: Get upload URL
  const { uploadUrl } = await zavu.regulatoryDocuments.uploadUrl();

  // Step 2: Upload the file to Convex storage
  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 document = await zavu.regulatoryDocuments.create({
    name: "John Doe Passport",
    documentType: "passport",
    storageId: storageId,
    mimeType: "image/jpeg",
    fileSize: fileBuffer.byteLength,
  });

  console.log("Document ID:", document.id);
  console.log("Status:", document.status);
  ```

  ```python Python theme={null}
  # Step 1: Get upload URL
  upload_result = zavu.regulatory_documents.upload_url()

  # Step 2: Upload the file to Convex storage
  import requests
  with open("passport.jpg", "rb") as f:
      file_data = f.read()
      response = requests.post(
          upload_result.upload_url,
          headers={"Content-Type": "image/jpeg"},
          data=file_data
      )
      storage_id = response.json()["storageId"]

  # Step 3: Create document record with the storageId
  document = zavu.regulatory_documents.create(
      name="John Doe Passport",
      document_type="passport",
      storage_id=storage_id,
      mime_type="image/jpeg",
      file_size=len(file_data)
  )

  print("Document ID:", document.id)
  print("Status:", document.status)
  ```

  ```ruby Ruby theme={null}
  # Step 1: Get upload URL
  upload_result = client.regulatory_documents.upload_url

  # Step 2: Upload the file to Convex storage
  require "net/http"
  file_data = File.binread("passport.jpg")
  uri = URI(upload_result.upload_url)
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  request = Net::HTTP::Post.new(uri)
  request["Content-Type"] = "image/jpeg"
  request.body = file_data
  response = http.request(request)
  storage_id = JSON.parse(response.body)["storageId"]

  # Step 3: Create document record with the storageId
  document = client.regulatory_documents.create(
    name: "John Doe Passport",
    document_type: "passport",
    storage_id: storage_id,
    mime_type: "image/jpeg",
    file_size: file_data.bytesize
  )

  puts "Document ID: #{document.id}"
  puts "Status: #{document.status}"
  ```

  ```go Go theme={null}
  // Step 1: Get upload URL
  uploadResult, _ := client.RegulatoryDocuments.UploadURL(context.TODO())

  // Step 2: Upload the file to Convex storage
  fileData, _ := os.ReadFile("passport.jpg")
  req, _ := http.NewRequest("POST", uploadResult.UploadURL, bytes.NewReader(fileData))
  req.Header.Set("Content-Type", "image/jpeg")
  resp, _ := http.DefaultClient.Do(req)
  var uploadResp struct{ StorageID string `json:"storageId"` }
  json.NewDecoder(resp.Body).Decode(&uploadResp)

  // Step 3: Create document record with the storageId
  document, _ := client.RegulatoryDocuments.Create(context.TODO(), zavudev.RegulatoryDocumentCreateParams{
  	Name:         zavudev.String("John Doe Passport"),
  	DocumentType: zavudev.String("passport"),
  	StorageID:    zavudev.String(uploadResp.StorageID),
  	MimeType:     zavudev.String("image/jpeg"),
  	FileSize:     zavudev.Int(len(fileData)),
  })

  fmt.Println("Document ID:", document.ID)
  fmt.Println("Status:", document.Status)
  ```

  ```php PHP theme={null}
  // Step 1: Get upload URL
  $uploadResult = $client->regulatoryDocuments->uploadUrl();

  // Step 2: Upload the file to Convex storage
  $fileData = file_get_contents('passport.jpg');
  $ch = curl_init($uploadResult->uploadUrl);
  curl_setopt($ch, CURLOPT_POST, true);
  curl_setopt($ch, CURLOPT_POSTFIELDS, $fileData);
  curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: image/jpeg']);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  $response = json_decode(curl_exec($ch));
  curl_close($ch);
  $storageId = $response->storageId;

  // Step 3: Create document record with the storageId
  $document = $client->regulatoryDocuments->create([
      'name' => 'John Doe Passport',
      'documentType' => 'passport',
      'storageId' => $storageId,
      'mimeType' => 'image/jpeg',
      'fileSize' => strlen($fileData),
  ]);

  echo "Document ID: {$document->id}\n";
  echo "Status: {$document->status}\n";
  ```

  ```bash cURL theme={null}
  # Step 1: Get upload URL
  curl -X POST https://api.zavu.dev/v1/documents/upload-url \
    -H "Authorization: Bearer $ZAVU_API_KEY"

  # Step 2: Upload file to the returned URL (returns storageId)
  STORAGE_ID=$(curl -X POST "$UPLOAD_URL" \
    -H "Content-Type: image/jpeg" \
    --data-binary @passport.jpg | jq -r '.storageId')

  # Step 3: Create document record
  curl -X POST https://api.zavu.dev/v1/documents \
    -H "Authorization: Bearer $ZAVU_API_KEY" \
    -H "Content-Type: application/json" \
    -d "{
      \"name\": \"John Doe Passport\",
      \"documentType\": \"passport\",
      \"storageId\": \"$STORAGE_ID\",
      \"mimeType\": \"image/jpeg\",
      \"fileSize\": 102400
    }"
  ```
</CodeGroup>

### Supported Document Types

| Type                    | Description                         |
| ----------------------- | ----------------------------------- |
| `passport`              | Government-issued passport          |
| `national_id`           | National identity card              |
| `drivers_license`       | Driver's license                    |
| `utility_bill`          | Utility bill (for proof of address) |
| `tax_id`                | Tax identification document         |
| `business_registration` | Business registration certificate   |
| `proof_of_address`      | Bank statement or official letter   |
| `other`                 | Other document type                 |

### File Requirements

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

### Document Statuses

| Status     | Description                                 |
| ---------- | ------------------------------------------- |
| `pending`  | Document uploaded and awaiting review       |
| `uploaded` | Document received and processing            |
| `verified` | Document verified and accepted              |
| `rejected` | Document rejected (check `rejectionReason`) |

## Purchasing with Requirements

Once you have your addresses and documents ready, include them in your purchase:

<CodeGroup>
  ```typescript TypeScript theme={null}
  const phoneNumber = await zavu.phoneNumbers.purchase({
    phoneNumber: "+4930123456789",
    name: "Germany Line",
    regulatoryRequirements: [
      {
        requirementType: "rt_address_de",
        fieldValue: "addr_abc123",
      },
      {
        requirementType: "rt_id_document",
        fieldValue: "doc_xyz789",
      },
    ],
  });
  ```

  ```python Python theme={null}
  phone_number = zavu.phone_numbers.purchase(
      phone_number="+4930123456789",
      name="Germany Line",
      regulatory_requirements=[
          {
              "requirement_type": "rt_address_de",
              "field_value": "addr_abc123"
          },
          {
              "requirement_type": "rt_id_document",
              "field_value": "doc_xyz789"
          }
      ]
  )
  ```

  ```ruby Ruby theme={null}
  phone_number = client.phone_numbers.purchase(
    phone_number: "+4930123456789",
    name: "Germany Line",
    regulatory_requirements: [
      { requirement_type: "rt_address_de", field_value: "addr_abc123" },
      { requirement_type: "rt_id_document", field_value: "doc_xyz789" }
    ]
  )
  ```

  ```go Go theme={null}
  phoneNumber, _ := client.PhoneNumbers.Purchase(context.TODO(), zavudev.PhoneNumberPurchaseParams{
  	PhoneNumber: zavudev.String("+4930123456789"),
  	Name:        zavudev.String("Germany Line"),
  	RegulatoryRequirements: []zavudev.RegulatoryRequirement{
  		{RequirementType: "rt_address_de", FieldValue: "addr_abc123"},
  		{RequirementType: "rt_id_document", FieldValue: "doc_xyz789"},
  	},
  })
  ```

  ```php PHP theme={null}
  $phoneNumber = $client->phoneNumbers->purchase([
      'phoneNumber' => '+4930123456789',
      'name' => 'Germany Line',
      'regulatoryRequirements' => [
          ['requirementType' => 'rt_address_de', 'fieldValue' => 'addr_abc123'],
          ['requirementType' => 'rt_id_document', 'fieldValue' => 'doc_xyz789'],
      ],
  ]);
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.zavu.dev/v1/phone-numbers \
    -H "Authorization: Bearer $ZAVU_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "phoneNumber": "+4930123456789",
      "name": "Germany Line",
      "regulatoryRequirements": [
        {
          "requirementType": "rt_address_de",
          "fieldValue": "addr_abc123"
        },
        {
          "requirementType": "rt_id_document",
          "fieldValue": "doc_xyz789"
        }
      ]
    }'
  ```
</CodeGroup>

<Warning>
  All required documents and addresses must have a `verified` or `pending` status before they can be used in a purchase request.
</Warning>

## Managing Addresses

### List Addresses

<CodeGroup>
  ```typescript TypeScript theme={null}
  const result = await zavu.addresses.list();

  for (const address of result.items) {
    console.log(address.id, address.streetAddress, address.status);
  }
  ```

  ```python Python theme={null}
  result = zavu.addresses.list()

  for address in result.items:
      print(address.id, address.street_address, address.status)
  ```

  ```ruby Ruby theme={null}
  result = client.addresses.list

  result.items.each do |address|
    puts "#{address.id} #{address.street_address} #{address.status}"
  end
  ```

  ```go Go theme={null}
  result, _ := client.Addresses.List(context.TODO(), zavudev.AddressListParams{})

  for _, address := range result.Items {
  	fmt.Println(address.ID, address.StreetAddress, address.Status)
  }
  ```

  ```php PHP theme={null}
  $result = $client->addresses->list();

  foreach ($result->items as $address) {
      echo "{$address->id} {$address->streetAddress} {$address->status}\n";
  }
  ```

  ```bash cURL theme={null}
  curl "https://api.zavu.dev/v1/addresses" \
    -H "Authorization: Bearer $ZAVU_API_KEY"
  ```
</CodeGroup>

### Delete Address

<CodeGroup>
  ```typescript TypeScript theme={null}
  await zavu.addresses.delete("addr_abc123");
  ```

  ```python Python theme={null}
  zavu.addresses.delete("addr_abc123")
  ```

  ```ruby Ruby theme={null}
  client.addresses.delete("addr_abc123")
  ```

  ```go Go theme={null}
  client.Addresses.Delete(context.TODO(), "addr_abc123")
  ```

  ```php PHP theme={null}
  $client->addresses->delete('addr_abc123');
  ```

  ```bash cURL theme={null}
  curl -X DELETE https://api.zavu.dev/v1/addresses/addr_abc123 \
    -H "Authorization: Bearer $ZAVU_API_KEY"
  ```
</CodeGroup>

<Warning>
  You cannot delete an address that is currently being used for an active phone number.
</Warning>

## Managing Documents

### List Documents

<CodeGroup>
  ```typescript TypeScript theme={null}
  const result = await zavu.regulatoryDocuments.list();

  for (const doc of result.items) {
    console.log(doc.id, doc.name, doc.status);
  }
  ```

  ```python Python theme={null}
  result = zavu.regulatory_documents.list()

  for doc in result.items:
      print(doc.id, doc.name, doc.status)
  ```

  ```ruby Ruby theme={null}
  result = client.regulatory_documents.list

  result.items.each do |doc|
    puts "#{doc.id} #{doc.name} #{doc.status}"
  end
  ```

  ```go Go theme={null}
  result, _ := client.RegulatoryDocuments.List(context.TODO(), zavudev.RegulatoryDocumentListParams{})

  for _, doc := range result.Items {
  	fmt.Println(doc.ID, doc.Name, doc.Status)
  }
  ```

  ```php PHP theme={null}
  $result = $client->regulatoryDocuments->list();

  foreach ($result->items as $doc) {
      echo "{$doc->id} {$doc->name} {$doc->status}\n";
  }
  ```

  ```bash cURL theme={null}
  curl "https://api.zavu.dev/v1/documents" \
    -H "Authorization: Bearer $ZAVU_API_KEY"
  ```
</CodeGroup>

### Delete Document

<CodeGroup>
  ```typescript TypeScript theme={null}
  await zavu.regulatoryDocuments.delete("doc_xyz789");
  ```

  ```python Python theme={null}
  zavu.regulatory_documents.delete("doc_xyz789")
  ```

  ```ruby Ruby theme={null}
  client.regulatory_documents.delete("doc_xyz789")
  ```

  ```go Go theme={null}
  client.RegulatoryDocuments.Delete(context.TODO(), "doc_xyz789")
  ```

  ```php PHP theme={null}
  $client->regulatoryDocuments->delete('doc_xyz789');
  ```

  ```bash cURL theme={null}
  curl -X DELETE https://api.zavu.dev/v1/documents/doc_xyz789 \
    -H "Authorization: Bearer $ZAVU_API_KEY"
  ```
</CodeGroup>

## Country-Specific Requirements

Here are common requirements for popular countries:

### Germany (DE)

* Local address within Germany
* Identity document (passport or national ID)
* Business registration (for business numbers)

### United Kingdom (GB)

* UK address
* Proof of identity
* Proof of address (utility bill or bank statement)

### France (FR)

* French address
* Identity document
* Proof of address

### Mexico (MX)

* Mexican address
* RFC (tax ID) for businesses
* Identity document

### Brazil (BR)

* Brazilian address
* CPF (individual) or CNPJ (business)
* Identity document

<Info>
  Requirements may change based on regulatory updates. Always check the current requirements using the API before purchasing.
</Info>

## Best Practices

<CardGroup cols={2}>
  <Card title="Prepare Documents First" icon="file-check">
    Upload and verify documents before attempting to purchase numbers.
  </Card>

  <Card title="Use Verified Addresses" icon="map-location-dot">
    Only verified addresses can be used for purchases. Allow time for verification.
  </Card>

  <Card title="Keep Documents Current" icon="clock">
    Ensure documents are not expired and information is up to date.
  </Card>

  <Card title="Check Requirements Early" icon="magnifying-glass">
    Query requirements during your planning phase to avoid purchase delays.
  </Card>
</CardGroup>

## Error Handling

| Error Code                 | Description                                            |
| -------------------------- | ------------------------------------------------------ |
| `requirements_missing`     | Purchase requires regulatory requirements not provided |
| `address_not_found`        | Referenced address ID doesn't exist                    |
| `document_not_found`       | Referenced document ID doesn't exist                   |
| `address_not_verified`     | Address must be verified before use                    |
| `document_not_verified`    | Document must be verified before use                   |
| `invalid_requirement_type` | Requirement type ID is not valid for this purchase     |

## Next Steps

<CardGroup cols={2}>
  <Card title="Purchase Phone Numbers" icon="phone" href="/guides/phone-numbers/purchasing">
    Learn about the full purchase process
  </Card>

  <Card title="Create Senders" icon="paper-plane" href="/concepts/senders">
    Set up senders to start messaging
  </Card>
</CardGroup>
