Inventory
Virtual numbers are the core asset in your telecommunications platform. On this page, we'll dive into the different inventory endpoints you can use to manage virtual numbers programmatically. We'll look at how to query and analyze your number inventory, and how to return numbers you no longer need.
All endpoints are scoped to your customer account via the {customer_slug} path segment and are authenticated with an API key sent as Authorization: Bearer xn_... (alternatively via the X-API-Key header). You can create API keys in the portal under Settings → API Keys.
The number model
The number model contains all the information about virtual numbers in your inventory, including their lifecycle status, geographical details, capabilities, and assignment timing. Phone numbers are stored and returned as bare digits including the country code, with no leading + (e.g. 12125551234).
Properties
- Name
number_id- Type
- uuid
- Description
Unique identifier for the virtual number.
- Name
number- Type
- string
- Description
The phone number as bare digits with country code, no leading "+" (e.g. "12125551234").
- Name
number_type- Type
- string
- Description
Number type (e.g., "local", "mobile").
- Name
country_code- Type
- string
- Description
ISO 3166-1 alpha-2 country code for the number (e.g., "US", "GB").
- Name
status- Type
- string
- Description
Lifecycle status: "active", "suspended", or "returned".
- Name
capabilities- Type
- array
- Description
Array of supported features, e.g. ["voice", "sms"]. May be null.
- Name
assigned_at- Type
- timestamp
- Description
Timestamp when the number was assigned to your account. May be null.
- Name
created_at- Type
- timestamp
- Description
Timestamp when the number record was created.
- Name
updated_at- Type
- timestamp
- Description
Timestamp when the number record was last updated.
List all numbers
This endpoint allows you to retrieve a paginated list of all virtual numbers assigned to your customer account with optional filters. By default, a maximum of 10 numbers are shown per page.
Path parameters
- Name
customer_slug- Type
- string
- Description
The unique slug identifier for the customer account.
Query parameters
- Name
page- Type
- integer
- Description
Page number for pagination (default: 1, min: 1).
- Name
limit- Type
- integer
- Description
Number of results per page (default: 10, min: 1, max: 100).
- Name
search- Type
- string
- Description
Search term to filter numbers.
- Name
number- Type
- string
- Description
Filter by an exact phone number (bare digits with country code).
- Name
number_type- Type
- string
- Description
Filter by number type. Accepts comma-separated values (e.g., "mobile,local").
- Name
country_code- Type
- string
- Description
Filter by ISO country code. Accepts comma-separated values (e.g., "US,CA").
- Name
status- Type
- string
- Description
Filter by status: "active", "suspended", or "returned". Accepts comma-separated values (e.g., "active,suspended").
- Name
capabilities- Type
- array
- Description
Filter by capabilities (repeat the parameter for multiple values).
- Name
assigned_from- Type
- string
- Description
Filter numbers assigned on or after this date (ISO 8601).
- Name
assigned_to- Type
- string
- Description
Filter numbers assigned on or before this date (ISO 8601).
- Name
sort_by- Type
- string
- Description
Field to sort by. Options: 'number', 'number_type', 'country_code', 'status', 'assigned_at', 'created_at', 'updated_at' (default: 'created_at').
- Name
sort_order- Type
- string
- Description
Sort direction. Options: 'asc', 'desc' (default: 'desc').
Request
curl -G https://api.xnumbers.io/api/customers/acme/numbers \
-H "Authorization: Bearer xn_your_api_key" \
-d page=1 \
-d limit=10 \
-d country_code=US \
-d number_type=local \
-d status=active
Response
{
"data": [
{
"number_id": "550e8400-e29b-41d4-a716-446655440000",
"number": "12125551234",
"number_type": "local",
"country_code": "US",
"status": "active",
"capabilities": ["voice", "sms"],
"assigned_at": "2024-01-15T10:30:00.000Z",
"created_at": "2024-01-01T00:00:00.000Z",
"updated_at": "2024-01-15T14:30:00.000Z"
},
{
"number_id": "550e8400-e29b-41d4-a716-446655440001",
"number": "12125555678",
"number_type": "local",
"country_code": "US",
"status": "active",
"capabilities": ["voice", "sms"],
"assigned_at": "2024-01-10T08:15:00.000Z",
"created_at": "2024-01-01T00:00:00.000Z",
"updated_at": "2024-01-10T08:15:00.000Z"
}
],
"meta": {
"total": 25,
"page": 1,
"limit": 10,
"totalPages": 3,
"hasNextPage": true,
"hasPreviousPage": false
}
}
Retrieve a number
This endpoint allows you to retrieve detailed information about a single virtual number in your account by providing its unique identifier.
Path parameters
- Name
customer_slug- Type
- string
- Description
The unique slug identifier for the customer account.
- Name
number_id- Type
- uuid
- Description
The unique identifier for the number.
Request
curl https://api.xnumbers.io/api/customers/acme/numbers/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer xn_your_api_key"
Response
{
"number_id": "550e8400-e29b-41d4-a716-446655440000",
"number": "12125551234",
"number_type": "local",
"country_code": "US",
"status": "active",
"capabilities": ["voice", "sms"],
"assigned_at": "2024-01-15T10:30:00.000Z",
"created_at": "2024-01-01T00:00:00.000Z",
"updated_at": "2024-01-15T14:30:00.000Z"
}
Get number statistics
This endpoint returns statistical data about your number inventory, providing total counts broken down by status with optional filtering by number type and country code. Useful for reporting and inventory management.
Path parameters
- Name
customer_slug- Type
- string
- Description
The unique slug identifier for the customer account.
Query parameters
- Name
number_type- Type
- string
- Description
Filter by number type (e.g., 'mobile', 'local').
- Name
country_code- Type
- string
- Description
Filter by country code (2-letter ISO format, e.g., 'US').
Request
curl -G https://api.xnumbers.io/api/customers/acme/numbers/stats \
-H "Authorization: Bearer xn_your_api_key" \
-d number_type=local \
-d country_code=US
Response
{
"total_numbers": 400,
"breakdown": {
"active": 312,
"suspended": 15,
"returned": 73
},
"generated_at": "2024-01-24T10:00:00.000Z"
}
Get number facets
This endpoint returns facet counts for your number inventory — counts of numbers grouped by status, number type, and country code. It is designed for building filter UIs and dashboards on top of the numbers list.
Path parameters
- Name
customer_slug- Type
- string
- Description
The unique slug identifier for the customer account.
Request
curl https://api.xnumbers.io/api/customers/acme/numbers/facets \
-H "Authorization: Bearer xn_your_api_key"
Response
{
"status": {
"active": 312,
"suspended": 15,
"returned": 73
},
"type": {
"mobile": 289,
"local": 111
},
"country": {
"GB": 250,
"US": 150
}
}
Export numbers to CSV
This endpoint exports your phone numbers to a CSV file. It accepts the same query parameters as the numbers list endpoint, so you can export a filtered subset of your inventory. The exported columns are: Number ID, Number, Number Type, Country Code, Status, Capabilities, Assigned At, Created At, Updated At.
Path parameters
- Name
customer_slug- Type
- string
- Description
The unique slug identifier for the customer account.
Query parameters
Same as List all numbers: search, number, number_type, country_code, status, capabilities, assigned_from, assigned_to, sort_by, sort_order.
Request
curl -G https://api.xnumbers.io/api/customers/acme/numbers/export/csv \
-H "Authorization: Bearer {token}" \
-d status=active \
-d country_code=US \
-o acme-numbers-export.csv
Returns the CSV file as a download with appropriate headers:
Content-Type: text/csvContent-Disposition: attachment; filename="acme-numbers-export-2024-01-24.csv"
Get number usage summary
This endpoint returns a daily usage summary for a specific number — voice calls, minutes, costs, and SMS counts — over the last N days. The daily breakdown is ordered oldest to newest and zero-filled for days with no traffic.
Path parameters
- Name
customer_slug- Type
- string
- Description
The unique slug identifier for the customer account.
- Name
number_id- Type
- uuid
- Description
The unique identifier for the number.
Query parameters
- Name
days- Type
- integer
- Description
Number of days to include in the summary (min: 1, max: 90, default: 14).
Request
curl -G https://api.xnumbers.io/api/customers/acme/numbers/550e8400-e29b-41d4-a716-446655440000/usage-summary \
-H "Authorization: Bearer xn_your_api_key" \
-d days=7
Response
{
"days": [
{
"date": "2024-01-14",
"calls": 42,
"voice_minutes": 127.5,
"voice_cost": 6.38,
"sms_count": 15,
"sms_cost": 1.5
},
{
"date": "2024-01-15",
"calls": 0,
"voice_minutes": 0,
"voice_cost": 0,
"sms_count": 0,
"sms_cost": 0
}
],
"totals": {
"calls": 294,
"voice_minutes": 892.5,
"sms_count": 105,
"total_cost": 44.63
}
}
Returning numbers
Numbers you no longer need are returned in bulk through return requests: you upload a CSV of phone numbers, which creates a pending request that requires admin approval before the numbers transition to the "returned" status. The return request model contains the request's status (pending, approved, rejected, or cancelled), file details, per-number processing counts, and approval/rejection information.
Properties
- Name
request_id- Type
- uuid
- Description
Unique identifier for the return request.
- Name
request_number- Type
- string
- Description
Human-readable request number (e.g., "#0001").
- Name
customer_id- Type
- uuid
- Description
Customer the return request belongs to.
- Name
customer_name- Type
- string
- Description
Company name of the customer. May be null.
- Name
file_name- Type
- string
- Description
Name of the uploaded CSV file.
- Name
status- Type
- string
- Description
Request status: "pending", "approved", "rejected", or "cancelled".
- Name
requested_by- Type
- uuid
- Description
User who created the request.
- Name
requested_by_name- Type
- string
- Description
Full name of the requesting user. May be null.
- Name
approved_by- Type
- uuid
- Description
User who approved the request. Null until approved.
- Name
approved_by_name- Type
- string
- Description
Full name of the approving user. May be null.
- Name
rejected_by- Type
- uuid
- Description
User who rejected the request. Null unless rejected.
- Name
rejected_by_name- Type
- string
- Description
Full name of the rejecting user. May be null.
- Name
processed_numbers_count- Type
- integer
- Description
Count of numbers processed so far.
- Name
total_numbers_count- Type
- integer
- Description
Total count of numbers in the request.
- Name
country- Type
- string
- Description
Country auto-derived from the matched numbers. May be null.
- Name
number_type- Type
- string
- Description
Number type auto-derived from the matched numbers. May be null.
- Name
notes- Type
- string
- Description
Notes provided with the request. May be null.
- Name
rejection_reason- Type
- string
- Description
Reason provided on rejection. May be null.
- Name
approval_note- Type
- string
- Description
Note provided on approval. May be null.
- Name
requested_at- Type
- timestamp
- Description
Timestamp when the request was submitted.
- Name
approved_at- Type
- timestamp
- Description
Timestamp of approval. Null until approved.
- Name
rejected_at- Type
- timestamp
- Description
Timestamp of rejection. Null unless rejected.
- Name
processed_at- Type
- timestamp
- Description
Timestamp when processing finished. Null until processed.
- Name
created_at- Type
- timestamp
- Description
Record creation timestamp.
- Name
updated_at- Type
- timestamp
- Description
Last record update timestamp.
- Name
created_by- Type
- uuid
- Description
User who created the record.
- Name
updated_by- Type
- uuid
- Description
User who last updated the record. May be null.
List return requests
This endpoint allows you to retrieve a paginated list of all return requests for your customer account, including their status, file information, and processing details. The response meta includes per-status counts for building filter tabs.
Path parameters
- Name
customer_slug- Type
- string
- Description
The unique slug identifier for the customer account.
Query parameters
- Name
page- Type
- integer
- Description
Page number for pagination (default: 1, min: 1).
- Name
limit- Type
- integer
- Description
Number of return requests per page (default: 10, min: 1).
- Name
status- Type
- string
- Description
Filter by status: 'pending', 'approved', 'rejected', 'cancelled'. Accepts comma-separated values.
- Name
requested_by- Type
- uuid
- Description
Filter by the user who created the request.
- Name
approved_by- Type
- uuid
- Description
Filter by the user who approved/rejected the request.
- Name
requested_from- Type
- string
- Description
Filter requests submitted on or after this date (ISO 8601).
date_fromis also accepted.
- Name
requested_to- Type
- string
- Description
Filter requests submitted on or before this date (ISO 8601).
date_tois also accepted.
- Name
search- Type
- string
- Description
Search term matched against file names.
- Name
sort_by- Type
- string
- Description
Field to sort by. Options: 'requested_at', 'status', 'file_name', 'total_numbers_count', 'processed_numbers_count', 'created_at', 'approved_at', 'processed_at' (default: 'requested_at').
- Name
sort_order- Type
- string
- Description
Sort direction. Options: 'asc', 'desc' (default: 'desc').
Request
curl -G https://api.xnumbers.io/api/customers/acme/return-requests \
-H "Authorization: Bearer xn_your_api_key" \
-d page=1 \
-d limit=10 \
-d status=pending
Response
{
"data": [
{
"request_id": "e650d145-bfc4-4f09-919f-af8927966ff1",
"request_number": "#0001",
"customer_id": "51d57d4f-90c3-4857-8d14-0c54f9a63af4",
"customer_name": "Acme Corp",
"file_name": "return_numbers.csv",
"status": "pending",
"requested_by": "3d93e518-9c8d-4af1-84af-2e52d9567604",
"requested_by_name": "Jane Doe",
"approved_by": null,
"approved_by_name": null,
"rejected_by": null,
"rejected_by_name": null,
"processed_numbers_count": 0,
"total_numbers_count": 100,
"country": "US",
"number_type": "local",
"notes": null,
"rejection_reason": null,
"approval_note": null,
"requested_at": "2024-01-24T01:49:33.929Z",
"approved_at": null,
"rejected_at": null,
"processed_at": null,
"created_at": "2024-01-24T01:49:33.929Z",
"updated_at": "2024-01-24T01:49:33.929Z",
"created_by": "3d93e518-9c8d-4af1-84af-2e52d9567604",
"updated_by": null
}
],
"meta": {
"total": 1,
"page": 1,
"limit": 10,
"totalPages": 1,
"hasNextPage": false,
"hasPreviousPage": false,
"status_counts": {
"pending": 1,
"approved": 0,
"rejected": 0,
"cancelled": 0
}
}
}
Retrieve a return request
This endpoint allows you to retrieve detailed information about a specific return request, including its current status, processing progress, and approval information.
Path parameters
- Name
customer_slug- Type
- string
- Description
The unique slug identifier for the customer account.
- Name
id- Type
- uuid
- Description
The unique identifier for the return request.
Request
curl https://api.xnumbers.io/api/customers/acme/return-requests/e650d145-bfc4-4f09-919f-af8927966ff1 \
-H "Authorization: Bearer xn_your_api_key"
Response
{
"request_id": "e650d145-bfc4-4f09-919f-af8927966ff1",
"request_number": "#0001",
"customer_id": "51d57d4f-90c3-4857-8d14-0c54f9a63af4",
"customer_name": "Acme Corp",
"file_name": "return_numbers.csv",
"status": "pending",
"requested_by": "3d93e518-9c8d-4af1-84af-2e52d9567604",
"requested_by_name": "Jane Doe",
"approved_by": null,
"approved_by_name": null,
"rejected_by": null,
"rejected_by_name": null,
"processed_numbers_count": 0,
"total_numbers_count": 100,
"country": "US",
"number_type": "local",
"notes": null,
"rejection_reason": null,
"approval_note": null,
"requested_at": "2024-01-24T01:49:33.929Z",
"approved_at": null,
"rejected_at": null,
"processed_at": null,
"created_at": "2024-01-24T01:49:33.929Z",
"updated_at": "2024-01-24T01:49:33.929Z",
"created_by": "3d93e518-9c8d-4af1-84af-2e52d9567604",
"updated_by": null
}
List return request numbers
This endpoint returns the individual phone numbers in a return request, paginated, with each row's processing status and enrichment (country_code and number_type from the matched number). The statistics object is always computed over all rows in the request, regardless of the status filter, while meta reflects the filtered result set.
Path parameters
- Name
customer_slug- Type
- string
- Description
The unique slug identifier for the customer account.
- Name
id- Type
- uuid
- Description
The unique identifier for the return request.
Query parameters
- Name
status- Type
- string
- Description
Filter by row status: 'pending', 'processed', 'failed', or 'skipped'.
- Name
search- Type
- string
- Description
Search by phone number (digits matched loosely; non-digits are stripped).
- Name
page- Type
- integer
- Description
Page number (default: 1, min: 1).
- Name
limit- Type
- integer
- Description
Items per page (default: 50, min: 1, max: 1000).
Request
curl -G https://api.xnumbers.io/api/customers/acme/return-requests/e650d145-bfc4-4f09-919f-af8927966ff1/numbers \
-H "Authorization: Bearer {token}" \
-d status=processed \
-d page=1 \
-d limit=50
Response
{
"data": [
{
"return_request_number_id": "7c0b2f3e-1d4a-4f6b-9c8d-2e5f7a9b1c3d",
"request_id": "e650d145-bfc4-4f09-919f-af8927966ff1",
"phone_number": "12125551234",
"csv_row_number": 1,
"status": "processed",
"number_id": "550e8400-e29b-41d4-a716-446655440000",
"error_code": null,
"error_message": null,
"processed_at": "2024-01-25T09:12:00.000Z",
"processed_by": "3d93e518-9c8d-4af1-84af-2e52d9567604",
"created_at": "2024-01-24T01:49:33.929Z",
"updated_at": "2024-01-25T09:12:00.000Z",
"created_by": "3d93e518-9c8d-4af1-84af-2e52d9567604",
"updated_by": "3d93e518-9c8d-4af1-84af-2e52d9567604",
"country_code": "US",
"number_type": "local"
}
],
"statistics": {
"total": 100,
"pending": 0,
"processed": 97,
"failed": 2,
"skipped": 1
},
"meta": {
"page": 1,
"limit": 50,
"total": 97,
"totalPages": 2
}
}
Upload a return request
This endpoint allows you to upload a CSV file containing phone numbers to create a return request. The created request is pending and requires admin approval before any numbers are returned. country and number_type are auto-derived from the matched numbers, and the response includes per-row matching statistics. Returns HTTP 201 on success.
Path parameters
- Name
customer_slug- Type
- string
- Description
The unique slug identifier for the customer account.
Required attributes
- Name
file- Type
- file
- Description
CSV file containing phone numbers to return (multipart/form-data, max 10MB).
Optional attributes
- Name
notes- Type
- string
- Description
Optional notes about the return request (max 1000 characters).
- Name
numberColumn- Type
- string
- Description
Column name (or 0-based index for headerless mode) containing the phone numbers.
- Name
hasHeader- Type
- string
- Description
Whether the CSV has a header row: 'true' or 'false' (default: auto-detect).
Request
curl -X POST https://api.xnumbers.io/api/customers/acme/return-requests/upload \
-H "Authorization: Bearer xn_your_api_key" \
-F "file=@phone_numbers.csv" \
-F "notes=End of service contract" \
-F "numberColumn=phone_number" \
-F "hasHeader=true"
Response
{
"request_id": "e650d145-bfc4-4f09-919f-af8927966ff1",
"request_number": "#0001",
"customer_id": "51d57d4f-90c3-4857-8d14-0c54f9a63af4",
"customer_name": "Acme Corp",
"file_name": "phone_numbers.csv",
"status": "pending",
"requested_by": "3d93e518-9c8d-4af1-84af-2e52d9567604",
"requested_by_name": "Jane Doe",
"approved_by": null,
"approved_by_name": null,
"rejected_by": null,
"rejected_by_name": null,
"processed_numbers_count": 0,
"total_numbers_count": 100,
"country": "US",
"number_type": "local",
"notes": "End of service contract",
"rejection_reason": null,
"approval_note": null,
"requested_at": "2024-01-24T01:49:33.929Z",
"approved_at": null,
"rejected_at": null,
"processed_at": null,
"created_at": "2024-01-24T01:49:33.929Z",
"updated_at": "2024-01-24T01:49:33.929Z",
"created_by": "3d93e518-9c8d-4af1-84af-2e52d9567604",
"updated_by": null,
"statistics": {
"total": 100,
"pending": 100,
"processed": 0,
"failed": 0,
"skipped": 0
}
}
Download return request CSV
This endpoint allows you to download the original CSV file that was uploaded for a specific return request.
Path parameters
- Name
customer_slug- Type
- string
- Description
The unique slug identifier for the customer account.
- Name
id- Type
- uuid
- Description
The unique identifier for the return request.
Request
curl https://api.xnumbers.io/api/customers/acme/return-requests/e650d145-bfc4-4f09-919f-af8927966ff1/download \
-H "Authorization: Bearer xn_your_api_key" \
-o phone_numbers.csv
Returns the CSV file as a download with appropriate headers:
Content-Type: text/csvContent-Disposition: attachment; filename="phone_numbers.csv"
Cancel a return request
This endpoint allows you to cancel a pending return request. Only requests that have not yet been approved or rejected can be cancelled. The response is the updated return request with status "cancelled".
Path parameters
- Name
customer_slug- Type
- string
- Description
The unique slug identifier for the customer account.
- Name
id- Type
- uuid
- Description
The unique identifier for the return request.
Optional attributes
- Name
notes- Type
- string
- Description
Optional notes explaining the cancellation.
Request
curl -X PATCH https://api.xnumbers.io/api/customers/acme/return-requests/e650d145-bfc4-4f09-919f-af8927966ff1/cancel \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"notes": "Uploaded the wrong file"
}'
Response
{
"request_id": "e650d145-bfc4-4f09-919f-af8927966ff1",
"request_number": "#0001",
"customer_id": "51d57d4f-90c3-4857-8d14-0c54f9a63af4",
"customer_name": "Acme Corp",
"file_name": "phone_numbers.csv",
"status": "cancelled",
"requested_by": "3d93e518-9c8d-4af1-84af-2e52d9567604",
"requested_by_name": "Jane Doe",
"approved_by": null,
"approved_by_name": null,
"rejected_by": null,
"rejected_by_name": null,
"processed_numbers_count": 0,
"total_numbers_count": 100,
"country": "US",
"number_type": "local",
"notes": "Uploaded the wrong file",
"rejection_reason": null,
"approval_note": null,
"requested_at": "2024-01-24T01:49:33.929Z",
"approved_at": null,
"rejected_at": null,
"processed_at": null,
"created_at": "2024-01-24T01:49:33.929Z",
"updated_at": "2024-01-25T11:02:14.103Z",
"created_by": "3d93e518-9c8d-4af1-84af-2e52d9567604",
"updated_by": "3d93e518-9c8d-4af1-84af-2e52d9567604"
}