# TextVerified developer API reference

> Generated from the public developer-only OpenAPI contract. Narrative guides explain purchase recovery and current rental restrictions.

Contract SHA256: `ef222fde5dd32a3f2f5e37b1a30779556446657afa7ffbbe38f524546dd55012`. Release date: 2026-10-30.

Base: `https://textverified.org/api/v1/developer`; reseller keys use their own store origin. Authenticate with `X-API-Key` or `Authorization: Bearer`. IDs are returned by the catalog or order API. Rental term-query durations are days; OTP term-query durations, purchase durations and order durations are milliseconds; prices are USD decimal strings. Every Phone Carrier Lookup API request costs USD0.05 and requires a persisted Idempotency-Key; it never consumes the dashboard free allowance.

SMS purchases require a saved `Idempotency-Key` and `maxPrice`. Proxy purchases require a current catalog offerKey and a saved Idempotency-Key; renewals are available only when the proxy supports them. Persist request keys for connect and reset too. See the proxy chapter for capability, connection-port and recovery details. Reconcile timeouts through purchase attempts. Rental `autoRenew`/`alwaysOn` creation options in the schema are currently rejected; auto-renew consent is dashboard-only. See [rentals](https://textverified.org/en/store-docs/rentals) and [retry handling](https://textverified.org/en/store-docs/errors-and-retries).

## Operations

### `POST /tools/phone-carrier-lookup`

Look up a phone carrier for USD0.05 from the API key account wallet

| Parameter | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| idempotency-key | header | yes | string |  |
| Idempotency-Key | header | yes | string | Reuse the same key and number for retries. A replay is not charged again. |

JSON body: `PhoneLookupDto`.

Response `200`: `PhoneLookupResponseDto`.

### `GET /tools/phone-carrier-lookup/{key}`

Recover an API lookup result without another charge (24-hour result retention)

| Parameter | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| key | path | yes | string |  |

Response `200`: `PhoneLookupResponseDto`.

### `GET /balance`

Get the balance of the account bound to this key

Response `200`: `DeveloperBalanceDto`.

### `GET /rentals/{rentalId}/services`

Quote additional services on an owned rental number

| Parameter | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| rentalId | path | yes | string |  |

Response `200`: `AdditionalRentalServicesDto`.

### `POST /rentals/{rentalId}/services`

Add a paid service to the same number for a separate seven-day rental

| Parameter | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| rentalId | path | yes | string |  |
| idempotency-key | header | yes | string |  |
| Idempotency-Key | header | yes | string |  |

JSON body: `AddRentalServiceInputDto`.

Response `200`: `CreateOrderResult`.

### `GET /services`

Browse services and current account prices

| Parameter | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| page | query | no | number |  |
| pageSize | query | no | number |  |
| name | query | no | string |  |
| type | query | yes | string (otp, rent) |  |
| countryCode | query | no | string |  |
| inStock | query | no | boolean |  |

Response `200`: `GetListServicesDto`.

### `GET /services/{serviceId}/durations`

Get available terms, stock and exact purchase prices

| Parameter | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| serviceId | path | yes | string |  |
| areaCode | query | no | string | Optional US area code; quote includes a one-time $1 fee per number |
| carrier | query | no | string (att, tmobile) | Carrier choice for US Unlimited rentals |
| countryCode | query | yes | string |  |
| providerId | query | no | string |  |
| kind | query | no | string (otp, rent) |  |

Response `200`: `GetListProviderServiceDurations`.

### `GET /verifications`

RetailDeveloperController_verifications

| Parameter | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| page | query | no | number |  |
| pageSize | query | no | number |  |
| view | query | no | string (active, history) | Active shows reserved orders; history shows completed, cancelled or expired orders. |
| number | query | no | string |  |
| status | query | no | string (reserved, successful, timeout, canceled, expired) |  |
| countryId | query | no | string |  |

Response `200`: `GetListVerificationsDto`.

### `POST /verifications`

Buy an OTP using an exact quote and an idempotency key

| Parameter | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| idempotency-key | header | yes | string |  |
| Idempotency-Key | header | yes | string | Reuse this key for retries of one purchase (8–128 letters, digits, underscores or hyphens). |

JSON body: `DeveloperCreateVerificationDto`.

Response `200`: `CreateOrderResult`.

### `GET /verifications/{id}`

RetailDeveloperController_verification

| Parameter | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| id | path | yes | string |  |

Response `200`: `GetVerificationDto`.

### `GET /verifications/{id}/messages`

RetailDeveloperController_verificationMessages

| Parameter | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| id | path | yes | string |  |
| page | query | no | number |  |
| pageSize | query | no | number |  |
| view | query | no | string (active, history) | Active shows reserved orders; history shows completed, cancelled or expired orders. |
| number | query | no | string |  |
| status | query | no | string (reserved, successful, timeout, canceled, expired) |  |
| countryId | query | no | string |  |

Response `200`: `GetListVerificationMessagesDto`.

### `POST /verifications/{id}/cancel`

RetailDeveloperController_cancelVerification

| Parameter | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| id | path | yes | string |  |

Response `200`: empty body.

### `GET /rentals`

RetailDeveloperController_rentals

| Parameter | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| page | query | no | number |  |
| pageSize | query | no | number |  |
| view | query | no | string (active, history) | Active shows reserved orders; history shows completed, cancelled or expired orders. |
| number | query | no | string |  |
| status | query | no | string (reserved, successful, timeout, canceled, expired) |  |
| countryId | query | no | string |  |

Response `200`: `GetListRentalNumbersDto`.

### `POST /rentals`

RetailDeveloperController_rent

| Parameter | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| idempotency-key | header | yes | string |  |
| Idempotency-Key | header | yes | string |  |

JSON body: `DeveloperRentNumberDto`.

Response `200`: `CreateOrderResult`.

### `GET /rentals/{id}`

RetailDeveloperController_rental

| Parameter | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| id | path | yes | string |  |

Response `200`: `GetRentalNumberDto`.

### `GET /rentals/{id}/messages`

RetailDeveloperController_rentalMessages

| Parameter | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| id | path | yes | string |  |
| page | query | no | number |  |
| pageSize | query | no | number |  |
| view | query | no | string (active, history) | Active shows reserved orders; history shows completed, cancelled or expired orders. |
| number | query | no | string |  |
| status | query | no | string (reserved, successful, timeout, canceled, expired) |  |
| countryId | query | no | string |  |

Response `200`: `GetListRentalMessagesDto`.

### `POST /rentals/{id}/cancel`

RetailDeveloperController_cancelRental

| Parameter | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| id | path | yes | string |  |

Response `200`: empty body.

### `GET /purchase-attempts/{key}`

Inspect a purchase attempt after a timeout before issuing another purchase

| Parameter | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| key | path | yes | string |  |

Response `200`: `DeveloperPurchaseAttemptDto`.

### `GET /proxy-products`

List mobile proxy products and durations

Response `200`: `ProxyProductListDto`.

### `GET /proxy-locations`

List mobile proxy locations

| Parameter | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| pricingCode | query | no | string | Return coverage for the selected currently available pricing option. |

Response `200`: `ProxyLocationListDto`.

### `GET /proxies`

List this account's proxies

| Parameter | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| status | query | no | string |  |

Response `200`: `array of ProxyDto`.

### `POST /proxies`

Buy a mobile proxy from wallet balance

| Parameter | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| idempotency-key | header | yes | string |  |
| Idempotency-Key | header | yes | string | Reuse the same key and body for retries; never charged twice. |

JSON body: `BuyProxyDto`.

Response `201`: `ProxyDto`.

### `GET /proxy-requests/{key}`

RetailDeveloperProxiesController_request

| Parameter | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| key | path | yes | string |  |

Response `200`: `ProxyDto`.

### `GET /proxies/{proxyId}`

Get one proxy

| Parameter | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| proxyId | path | yes | string |  |

Response `200`: `ProxyDto`.

### `GET /proxies/{proxyId}/locations`

List available locations for a proxy

| Parameter | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| proxyId | path | yes | string |  |

Response `200`: `ProxyLocationListDto`.

### `POST /proxies/{proxyId}/connect`

Connect a proxy to a US location

| Parameter | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| proxyId | path | yes | string |  |
| idempotency-key | header | yes | string |  |
| Idempotency-Key | header | no | string | Persist one key for this control request and reuse it after an uncertain response. |

JSON body: `ConnectProxyDto`.

Response `200`: `ProxyDto`.

### `POST /proxies/{proxyId}/disconnect`

Disconnect a proxy from its current location

| Parameter | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| proxyId | path | yes | string |  |

Response `200`: `ProxyDto`.

### `POST /proxies/{proxyId}/reset`

Rotate the proxy IP (fast or hard modem reset)

| Parameter | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| proxyId | path | yes | string |  |
| idempotency-key | header | yes | string |  |
| Idempotency-Key | header | no | string | Persist one key for this control request and reuse it after an uncertain response. |

JSON body: `ResetProxyDto`.

Response `200`: `ProxyDto`.

### `POST /proxies/{proxyId}/fingerprint`

Set the TCP fingerprint for a proxy

| Parameter | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| proxyId | path | yes | string |  |

JSON body: `SetProxyFingerprintDto`.

Response `200`: `ProxyDto`.

### `POST /proxies/{proxyId}/renew`

Renew an active proxy for the same duration

| Parameter | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| proxyId | path | yes | string |  |
| idempotency-key | header | yes | string |  |
| Idempotency-Key | header | yes | string |  |

JSON body: `RenewProxyDto`.

Response `200`: `ProxyDto`.

## Schemas

### PhoneLookupDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| number | yes | string | International phone number including country code. Spaces, parentheses and hyphens are accepted. |

### PhoneLookupResultDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| valid | yes | boolean |  |
| number | yes | string |  |
| internationalFormat | yes | string \| null |  |
| nationalFormat | yes | string \| null |  |
| carrier | yes | string \| null |  |
| lineType | yes | string \| null |  |
| countryCode | yes | string \| null |  |
| countryName | yes | string \| null |  |
| location | yes | string \| null |  |
| timezones | yes | array of string |  |

### PhoneLookupResponseDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| id | yes | string |  |
| result | yes | PhoneLookupResultDto |  |
| charged | yes | string |  |
| free | yes | boolean | Always false for API requests. |
| replayed | yes | boolean | True when returning the saved result of an identical request, with no additional charge. |

### DeveloperBalanceDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| accountId | yes | string |  |
| balance | yes | string |  |
| currency | yes | string |  |

### AdditionalRentalServiceDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| serviceId | yes | string |  |
| name | yes | string |  |
| price | yes | string | Additional total charge in USD |
| durationDays | yes | number | New independent term in days |

### AdditionalRentalServicesDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| items | yes | array of AdditionalRentalServiceDto |  |

### AddRentalServiceInputDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| serviceId | yes | string | Exact service ID from the additional-service quote |
| maxPrice | yes | string | Maximum additional charge in USD |

### CreateOrderResult

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| id | yes | string |  |
| number | yes | string |  |
| expiresAt | yes | string |  |
| createdAt | yes | string |  |

### GetRentalAreaCodeDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| areaCode | yes | string |  |
| state | yes | string |  |

### GetProviderServiceDurationOptionDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| code | yes | string |  |
| price | yes | string |  |

### GetProviderServiceDurationDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| areaCodePrice | no | string | Total price per number with a custom area code, including the $1 selection fee |
| carrier | no | string (att, tmobile) |  |
| options | yes | array of GetProviderServiceDurationOptionDto |  |
| id | yes | string |  |
| duration | yes | number | Days for rental terms (kind=rent); milliseconds for verification terms (kind=otp). Rental purchases always require milliseconds: multiply a rental term by 86400000. |
| human | yes | string |  |
| count | yes | number | Counted stock. A zero count is available only when onDemand=true; do not invent an inventory count. |
| capability | no | string (sms, voice, smsAndVoiceCombo) |  |
| onDemand | no | boolean | Available through on-demand provisioning without an inventory count |
| requiresActivation | no | boolean | Number activation must be confirmed before delivery and wallet charging |
| automaticCancellation | no | boolean | Whether automatic cancellation and refund are supported for this plan |
| price | yes | string |  |

### GetServiceDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| cachedPlans | no | object |  |
| category | no | string (ai, apple, applications, backgroundServices, banks, betting, businessServices, cashback, creditCardsLoans, creditUnion, crypto, datingApps, emailServices, financial, fuelServices, gambling, games, gifts, googleServices, infrastructure, investment, kycVerification, marketing, media, merchants, messengers, microsoft, musicStreaming, others, paypal, proxy, realEstate, reviews, rewards, samsung, services, socialMedia, sport, stores, surveys, taxServices, telecommunications, tickets, unlisted, vcc) |  |
| id | yes | string |  |
| name | yes | string |  |
| count | no | number |  |
| onDemand | no | boolean | At least one plan supports on-demand provisioning; count is not an inventory claim for that plan |
| minPrice | no | string |  |
| maxPrice | no | string |  |
| income | no | string |  |
| status | yes | object |  |
| markupKind | yes | object |  |
| markupValue | yes | string \| null |  |
| isFavorite | no | boolean |  |
| code | yes | string |  |
| icon | yes | string \| null |  |
| type | yes | string |  |

### GetListServicesDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| items | yes | array of GetServiceDto |  |
| page | yes | number |  |
| pageSize | yes | number |  |
| totalItems | yes | number |  |
| totalPages | yes | number |  |

### GetListProviderServiceDurations

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| items | yes | array of GetProviderServiceDurationDto |  |
| page | yes | number |  |
| pageSize | yes | number |  |
| totalItems | yes | number |  |
| totalPages | yes | number |  |

### OrderServiceDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| id | yes | string |  |
| name | yes | string |  |
| count | no | number |  |
| minPrice | no | string |  |
| maxPrice | no | string |  |
| income | no | string |  |
| isFavorite | no | boolean |  |
| code | yes | string |  |
| icon | yes | string \| null |  |
| type | yes | string |  |

### OrderProviderDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| id | yes | string |  |
| name | yes | string |  |

### GetCountryDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| id | yes | string |  |
| code | yes | string |  |

### GetVerificationDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| capability | yes | string (sms, voice, smsAndVoiceCombo) |  |
| id | yes | string |  |
| number | yes | string |  |
| duration | yes | number |  |
| description | yes | string \| null |  |
| totalPrice | yes | string |  |
| code | yes | string \| null |  |
| sms | yes | string \| null |  |
| status | yes | string |  |
| isTransfering | yes | boolean |  |
| isCancelable | yes | boolean |  |
| service | yes | object \| null |  |
| provider | yes | OrderProviderDto |  |
| country | yes | GetCountryDto |  |
| expiresAt | yes | string |  |
| createdAt | yes | string |  |
| updatedAt | yes | string |  |

### GetListVerificationsDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| items | yes | array of GetVerificationDto |  |
| page | yes | number |  |
| pageSize | yes | number |  |
| totalItems | yes | number |  |
| totalPages | yes | number |  |

### DeveloperCreateVerificationDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| capability | no | string (sms, voice) |  |
| duration | yes | number | Duration in ms |
| serviceId | yes | string |  |
| countryCode | yes | string |  |
| providerId | no | string |  |
| description | no | string |  |
| maxPrice | yes | string | Maximum total charge in USD, taken from the terms quote |

### GetVerificationMessageDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| id | yes | string |  |
| text | yes | string |  |
| code | yes | string \| null |  |
| verification | yes | GetVerificationDto |  |
| createdAt | yes | string |  |

### GetListVerificationMessagesDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| items | yes | array of GetVerificationMessageDto |  |
| page | yes | number |  |
| pageSize | yes | number |  |
| totalItems | yes | number |  |
| totalPages | yes | number |  |

### GetRentalNumberDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| canAddService | no | boolean | Whether this active rental supports purchasing another service on the same number |
| capability | yes | string (sms, voice, smsAndVoiceCombo) |  |
| id | yes | string |  |
| number | yes | string |  |
| duration | yes | number |  |
| description | yes | string \| null |  |
| totalPrice | yes | string |  |
| code | yes | string \| null |  |
| sms | yes | string \| null |  |
| status | yes | string |  |
| isTransfering | yes | boolean |  |
| isCancelable | yes | boolean |  |
| shouldRenew | yes | boolean |  |
| isAutoRenewEnabled | yes | boolean | TextVerified wallet-funded renewal preference; independent of supplier native auto-renew |
| canAutoRenew | yes | boolean | Whether this active rental supports wallet-funded auto-renew |
| supplierAutoRenewStatus | yes | string (unavailable, not_applicable) | Native supplier auto-renew cannot be read through the supported API; unavailable is not an off state |
| service | yes | object \| null |  |
| provider | yes | OrderProviderDto |  |
| country | yes | GetCountryDto |  |
| expiresAt | yes | string |  |
| createdAt | yes | string |  |
| updatedAt | yes | string |  |

### GetListRentalNumbersDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| items | yes | array of GetRentalNumberDto |  |
| page | yes | number |  |
| pageSize | yes | number |  |
| totalItems | yes | number |  |
| totalPages | yes | number |  |

### DeveloperRentNumberDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| areaCode | no | string | Optional US area code for T-Mobile Unlimited SMS rentals; adds $1 per number at purchase |
| carrier | no | string (att, tmobile) | Carrier choice for US Unlimited rentals |
| capability | no | string (sms, voice) |  |
| options | no | array of string (alwaysOn, autoRenew) |  |
| duration | yes | number | Duration in ms |
| serviceId | yes | string |  |
| countryCode | yes | string |  |
| providerId | no | string |  |
| description | no | string |  |
| maxPrice | yes | string | Maximum total charge in USD, taken from the terms quote |

### GetRentalMessageDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| id | yes | string |  |
| text | yes | string |  |
| code | yes | string \| null |  |
| rental | yes | GetRentalNumberDto |  |
| createdAt | yes | string |  |

### GetListRentalMessagesDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| items | yes | array of GetRentalMessageDto |  |
| page | yes | number |  |
| pageSize | yes | number |  |
| totalItems | yes | number |  |
| totalPages | yes | number |  |

### DeveloperPurchaseAttemptDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| key | yes | string |  |
| status | yes | string |  |
| activationId | yes | string \| null |  |
| recoveryState | yes | string \| null |  |
| error | yes | string \| null |  |
| createdAt | yes | string |  |

### ProxyCoverageDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| locationCount | yes | number |  |
| cityCount | yes | number | Distinct labeled city/state areas among listed choices. |
| stateCodes | yes | array of string |  |
| carriers | yes | array of string |  |

### ProxyPricingDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| coverage | no | object \| null |  |
| offerKey | yes | string |  |
| renewalSupported | yes | boolean |  |
| fingerprintSupported | yes | boolean |  |
| code | yes | string |  |
| label | yes | string |  |
| priceUsd | yes | string |  |
| periodType | yes | string |  |
| periodDuration | yes | number |  |

### ProxyProductDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| code | yes | string |  |
| name | yes | string |  |
| description | yes | object \| null |  |
| enabled | yes | boolean |  |
| pricingOptions | yes | array of ProxyPricingDto |  |

### ProxyProductListDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| products | yes | array of ProxyProductDto |  |

### ProxyLocationDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| city | no | string |  |
| stateCode | no | object \| null |  |
| carrier | no | object \| null |  |
| id | yes | string |  |
| location | yes | string |  |
| available | yes | number \| null |  |

### ProxyLocationListDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| locations | yes | array of ProxyLocationDto |  |

### ProxyDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| socks5Port | yes | object \| null |  |
| capabilities | yes | object |  |
| id | yes | string |  |
| name | yes | object |  |
| status | yes | string |  |
| productName | yes | string |  |
| pricingLabel | yes | string |  |
| pricingCode | yes | string |  |
| renewalPriceUsd | yes | string |  |
| renewalStatus | yes | string \| null (pending, completed, failed) |  |
| amountUsd | yes | string |  |
| ip | yes | object \| null |  |
| port | yes | object \| null |  |
| username | yes | object \| null |  |
| password | yes | object \| null |  |
| locationId | yes | object \| null |  |
| fingerprint | yes | string |  |
| expiresAt | yes | object \| null |  |
| error | yes | object \| null |  |
| createdAt | yes | string |  |

### BuyProxyDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| offerKey | no | string | Offer key from the current proxy catalog. Required when the available plan changes. |
| pricingCode | yes | string (hour_3, hour_1, day_1, day_2, week_1, month_1) |  |
| locationId | no | string | Connect to this location after provisioning |

### ConnectProxyDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| locationId | yes | string |  |

### ResetProxyDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| mode | yes | string (fast, hard) |  |

### SetProxyFingerprintDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| fingerprint | yes | string (none, linux, macos, windows) |  |

### RenewProxyDto

| Field | Required | Type | Description |
| --- | --- | --- | --- |
| maxAmountUsd | no | string | Maximum accepted renewal price in USD, from the current catalog. |

[Live OpenAPI JSON](https://textverified.org/api/v1/developer/openapi.json) · [Interactive docs](https://textverified.org/api/v1/developer/docs) · [Documentation index](https://textverified.org/en/store-docs/index)

---

# Email OTP API

Authenticate with your account API key in `X-API-Key`. All paths below start with `/api/v1/developer/email-otp`. Prices and wallet transactions use USD.

| Method | Path | Purpose |
| --- | --- | --- |
| GET | `/catalog` | Current service/domain offers, stock and prices |
| GET | `/activations` | Your most recent 100 activations |
| POST | `/activations` | Reserve funds and request an email address |
| GET | `/activations/{id}` | Read the saved activation |
| GET | `/activations/{id}/message` | Read the full received message |
| POST | `/activations/{id}/refresh` | Check for a verification code |
| POST | `/activations/{id}/cancel` | Request cancellation before a code arrives |

For a purchase, send a unique `Idempotency-Key` header (8–128 letters, digits, underscores or hyphens). Reuse it for retries of the same purchase. Read the catalog first, then send a JSON object with `service`, `domain` and `maxPrice`, such as `{"service":"ig","domain":"gmail.com","maxPrice":"0.17"}`. The example price is illustrative; use a current quote.

An activation returns `id`, `service`, `serviceName`, `domain`, `email`, `code`, `hasMessage`, `price`, `currency`, `status`, `cancelRequested`, `refunded`, `createdAt` and `updatedAt`. Only account-facing activation details are returned.

`code` contains only an extracted verification code, or `null` if no unambiguous code is detected. `hasMessage` indicates a saved full message. Use `GET /api/v1/developer/email-otp/activations/{id}/message` with the same account API key to retrieve `{ "id": "...", "message": "..." }`. Reading the message does not resend email or charge your wallet.

States: `allocating` (purchase confirmation pending), `waiting` (address ready), `completed` (code received), `canceled`, or `failed`. A code completes the charge. A confirmed cancellation or confirmed allocation failure refunds the original charge. Unknown outcomes stay reserved for review. Never repeat an uncertain purchase under a new key. Store the activation ID for support.

This is a temporary one-time verification service, not a permanent mailbox. SMS purchasing and SMS API routes are separate.

---

## All SMS stock for one country

`GET /api/v1/developer/stock?countryCode=US`

Send `X-API-Key: YOUR_API_KEY` on the same store origin as your account.
The response contains SMS verification and rental offers for one country,
with account prices, service totals and availability. There is no pagination.

`countryCode` is required (two-letter ISO code). Optional `type=otp` or
`type=rent` selects one product. By default only available services and offers
are returned; `inStock=false` also includes zero-stock quotes and visible
services with no current offers. All totals respect these filters.

- `totalServices`: distinct service IDs in the response, counted once even
  when a service appears in both OTP and rental rows.
- `availableServices`: distinct returned service IDs with counted inventory
  or an offer available on demand.
- `byType.otp` and `byType.rent`: those totals for each product separately.
- `totalItems`: number of rows in `items`; one row is one service/product pair.
- `items[].count`: largest offer count for that row. It is not a sum: different
  terms and carriers may share inventory. Offer-level counts remain in `offers`.
- `items[].available`: whether at least one offer has stock or is on demand.
- `items[].availability`: `in_stock`, `on_demand`, or `out_of_stock`.
- `items[].onDemand`: whether at least one offer can be requested on demand.

`on_demand` with `count: 0` means the service is requestable but no numeric
inventory count is available. It does not mean zero availability or unlimited
inventory. Counts across services can also overlap; do not sum them into a
country-wide number total. Availability can change before purchase.

Example response (illustrative values):

```json
{
  "generatedAt": "2026-10-27T12:00:00.000Z",
  "currency": "USD",
  "countryCode": "US",
  "totalItems": 1,
  "totalServices": 1,
  "availableServices": 1,
  "byType": {
    "otp": { "totalServices": 1, "availableServices": 1 },
    "rent": { "totalServices": 0, "availableServices": 0 }
  },
  "items": [
    {
      "serviceId": "SERVICE_ID_FROM_CATALOG",
      "serviceCode": "SERVICE_CODE",
      "serviceName": "Example service",
      "type": "otp",
      "countryCode": "US",
      "count": 12,
      "available": true,
      "onDemand": false,
      "availability": "in_stock",
      "offers": [
        {
          "id": "QUOTE_ID",
          "duration": 1200000,
          "human": "20 minutes",
          "price": "0.50",
          "count": 12,
          "onDemand": false
        }
      ]
    }
  ]
}
```

Prices are the account's current total USD prices. Every `duration` here is in
**milliseconds**, including rentals. Purchase with `serviceId`, `countryCode`,
`duration`, `maxPrice=price`, and `carrier` when returned. Existing single-service
`/durations` endpoints keep their original units.

The limit is **one request every 60 seconds per account and country**, shared
across all API keys, filters and API servers. A different country has an
independent limit. Additional requests return HTTP `429`, `STOCK_RATE_LIMITED`,
and `Retry-After` in seconds. Rejected requests do not extend the window.
Valid requests consume the window when processing starts, even if a later
catalog read fails. Invalid parameters do not consume it.

## Renew a number with an API key

Base URL: `https://textverified.org/api/v1/developer`. Use the same store hostname and API key as the original integration. Every operation is restricted to the account bound to the key; do not send `accountId`.

1. Read `GET /rentals/{id}/renewal` for the current renewal price, existing term in milliseconds, and current `expiresAt`.
2. Save a new `Idempotency-Key` for this intended renewal. Call `POST /rentals/{id}/renew` with JSON `{"maxPrice":"<quote price>","expectedExpiresAt":"<quote expiresAt>"}`. The key must contain 8–128 letters, digits, underscores or hyphens.
3. Read `GET /rentals/{id}/renewals/{renewalId}` to check the saved result. This read makes no renewal request or wallet charge.

Renewal adds the rental's **existing term** to the verified current expiry. It keeps the same number and does not change the dashboard auto-renew preference. Only eligible active SMS rentals can be renewed. Canceled or expired numbers cannot be reactivated, and a pending transfer must be canceled first. Eligibility depends on the original rental's supported renewal capability; an available new-number offer does not prove that an existing rental can be renewed.

The quote is read-only. Renewal checks eligibility, ownership, current price and wallet balance again. `maxPrice` is the maximum total USD charge, including applicable reseller pricing. `expectedExpiresAt` prevents an old quote from extending the number again after another renewal. The original one-time area-code selection fee is not charged again. Read and accept a fresh quote for each later renewal.

Example, using values read from the quote:

```sh
BASE=https://textverified.org/api/v1/developer
# Set API_KEY, RENTAL_ID and a unique RENEWAL_KEY in your server environment.
QUOTE=$(curl --fail-with-body -sS "$BASE/rentals/$RENTAL_ID/renewal" \
  -H "X-API-Key: $API_KEY")
BODY=$(printf '%s' "$QUOTE" | jq '{maxPrice: .price, expectedExpiresAt: .expiresAt}')
# Persist RENEWAL_KEY and BODY before sending. Retries must reuse both.
curl --fail-with-body -sS "$BASE/rentals/$RENTAL_ID/renew" \
  -H "X-API-Key: $API_KEY" -H 'Content-Type: application/json' \
  -H "Idempotency-Key: $RENEWAL_KEY" -d "$BODY"
```

The renewal response includes `rentalId`, `renewalId`, `status`, `currency`, `price`, `duration`, `previousExpiresAt`, `expiresAt` and `refunded`.

- `completed`: the new expiry is confirmed and returned in `expiresAt`.
- `pending`: the price is reserved from the wallet while confirmation is checked; `expiresAt` is null. Retain the original key and body. A timeout does not prove failure. Retry only that same request, or poll the status endpoint. **Never use a new key to bypass a pending result.** The worker checks confirmation without submitting the renewal again. Contact support if it remains pending.
- `failed`: the renewal was not confirmed as successful and the reserved amount was returned; `refunded` is true and `expiresAt` is null. Replaying the key returns this same saved result.

Missing or invalid keys return 401. An unowned or missing rental/renewal returns 404. Invalid input, an unsupported rental, an insufficient balance or a price over `maxPrice` returns 400. HTTP 409 means a changed expiry, conflicting idempotency key, pending transfer or pending renewal. A quote that cannot be verified returns 503 before any charge. Account deposit restrictions can return 403. Read the response `code` and message for details.

API-key renewal does not enable automatic renewal. The dashboard remains the place to change auto-renew consent. Proxy renewal uses its separate endpoint and contract.
