# SMS Verification Number Registry (`nalineerattanaporn/sms-verification-number-registry`) Actor

Sort and check SMS verification numbers by project, market and team: expiry status and duplicate numbers.

- **URL**: https://apify.com/nalineerattanaporn/sms-verification-number-registry.md
- **Developed by:** [Nalinee Rattanaporn](https://apify.com/nalineerattanaporn) (community)
- **Categories:** Developer tools
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-usage

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### SMS Verification Number Registry: keep verification numbers sorted by project, market and team

When a team registers test accounts, customer-service accounts and recovery contacts across several markets, the phone numbers that receive verification SMS end up in chats and personal notes. This Actor takes a plain list of those numbers and returns one sorted registry with the expiry status of every number and the duplicates that are shared between projects.

#### What the Actor does

- Sorts records by project, then market, then team, so each coordinator sees their own block.
- Calculates `daysLeft` for every number from its `expiresOn` date and assigns a status: `expired`, `expiring` (within the chosen number of days), `active` or `no-expiry`.
- Flags a number that appears more than once (`duplicateOf` points to the first row with the same number), which is how a code for a new account ends up on an old agent's phone.
- Writes the registry to the run's dataset (CSV, JSON, Excel export) and a short `SUMMARY` record to the key-value store with the counts per status.

#### How to use SMS Verification Number Registry

1. Open the Actor and paste your records into **Number records** as a JSON array. Each record has `project`, `market`, `team`, `purpose`, `number`, `provider`, `owner` and `expiresOn` (YYYY-MM-DD). Missing fields are allowed.
2. Set **Expiring within (days)** if you want a warning earlier or later than 7 days.
3. Optionally set **Reference date** to run the check against a fixed date.
4. Click **Start**. The result appears in the **Output** tab and can be downloaded or fetched through the API.

#### Example result

Input: five numbers for two projects. Output (dataset, view *Registry*):

| project | market | team | number | expiresOn | daysLeft | status | duplicateOf |
|---|---|---|---|---|---|---|---|
| Onboarding app | ID | QA | +6281200000001 | 2026-10-30 | 3 | expiring | |
| Onboarding app | ID | Support | +6281200000002 | 2027-06-01 | 217 | active | |
| Onboarding app | TH | QA | +66800000003 | 2026-10-01 | -26 | expired | |
| Payments | ID | QA | +6281200000001 | 2026-11-15 | 19 | active | 1 |
| Payments | VN | Support | +84900000005 | | | no-expiry | |

`SUMMARY`: `{"total":5,"expired":1,"expiring":1,"active":2,"no-expiry":1,"duplicates":1}`

#### Limitations

- The Actor does not connect to any SMS provider and does not receive messages. It only organises the list you give it.
- Numbers are compared after removing spaces and punctuation; a number written with and without the country code counts as two different numbers.
- Dates are read as UTC calendar dates.

***

### Cara Memisahkan SMS Verifikasi Berdasarkan Proyek, Pasar, dan Tim

![](https://api.apify.com/v2/key-value-stores/PN0G43sX3fhvwCQlZ/records/image1.png)

Sebuah akun pengujian selesai dibuat, tetapi kemudian kode masuk justru dikirim ke nomor agen lama. Ini mengingatkan saya pada pemisahan jalur SMS sejak awal. Dalam dukungan regional, nomor virtual membantu menjaga akses kerja tetap teratur. nomor sementara <https://hottelecom.biz/id/disposable-sms-phone-numbers.html> berguna bagi kebutuhan terbatas, sementara akun penting memerlukan pengelolaan yang jelas.

#### Mengelompokkan kebutuhan sebelum memilih nomor

Saya membagi kebutuhan menurut pasar, proyek, dan tim. Satu proyek dapat melibatkan beberapa negara tanpa nomor khusus bagi tiap orang. Sebaliknya, akun pengujian dan akun layanan pelanggan sebaiknya memiliki catatan akses yang terpisah karena masa pakainya berbeda.

Untuk sms sementara, saya memeriksa apakah kode hanya dibutuhkan saat pengujian atau mungkin diminta kembali saat pemulihan akun. Informasi itu menentukan pilihan nomor dan siapa yang boleh mengakses pesan. Pembagian berdasarkan fungsi juga membantu rekan lain menemukan pemilik proses tanpa menghubungi pendaftar.

#### Membedakan akses singkat dari akun yang perlu dipertahankan

Penawaran no hp sekali pakai terlihat cocok bagi satu sesi. Akan tetapi, sebelum menggunakannya, saya memastikan metode penerimaan SMS diizinkan oleh platform tujuan. Untuk akun kerja yang terus digunakan, kemampuan mempertahankan akses jauh lebih penting daripada cepatnya menerima kode pertama.

Keputusan beli nomor sekali pakai juga perlu dikaitkan dengan rencana proyek. Saya mencatat penyedia, batas masa penggunaan, penanggung jawab, dan kemungkinan adanya verifikasi ulang. Jika sebuah aplikasi memerlukan nomor yang tetap aktif, tim harus memilih opsi yang mendukung kebutuhan tersebut. Saya tidak ingin pergantian petugas membuat tim kehilangan jalur pemulihan yang diperlukan.

#### Menjaga kepemilikan dan serah terima tetap jelas

Dalam proses nomor sementara untuk verifikasi, kode autentikasi hanya ditangani oleh pengelola yang berwenang. Catatan tentang fungsi akun dapat dibagikan kepada tim, tetapi kode dan informasi pemulihan disimpan melalui mekanisme keamanan yang disetujui. Agen yang melayani pelanggan cukup memperoleh akses sesuai pekerjaannya, tanpa harus menerima seluruh pesan keamanan.

Istilah nomor hp 10 menit menggambarkan pilihan dengan durasi sangat singkat. Saya menilai durasi itu berdasarkan kebutuhan nyata, bukan sebagai solusi untuk seluruh registrasi. Bagi saya, sistem yang baik memungkinkan koordinator baru memahami status akun, mengetahui siapa pemilik akses, dan melanjutkan pekerjaan tanpa bergantung pada telepon pribadi orang sebelumnya. Ketika struktur ini diterapkan secara konsisten, SMS verifikasi menjadi bagian dari operasi yang tertib, bukan sumber kebingungan saat tim dan pasar bertambah. Saya menyarankan koordinator meninjau daftar akun sebelum proyek dimulai. Langkah ini pun memudahkan kerja sama dan mencegah nomor terlewat.

# Actor input Schema

## `records` (type: `array`):

One object per number: project, market, team, purpose, number, provider, owner, expiresOn (YYYY-MM-DD).

## `expiringWithinDays` (type: `integer`):

Numbers whose expiry date is within this many days get status "expiring".

## `today` (type: `string`):

Optional YYYY-MM-DD used instead of the current date, for reproducible runs.

## Actor input object example

```json
{
  "records": [
    {
      "project": "Onboarding app",
      "market": "ID",
      "team": "QA",
      "purpose": "test account",
      "number": "+62 812 0000 0001",
      "provider": "virtual",
      "owner": "Dewi",
      "expiresOn": "2026-10-30"
    },
    {
      "project": "Onboarding app",
      "market": "ID",
      "team": "Support",
      "purpose": "customer account",
      "number": "+62 812 0000 0002",
      "provider": "SIM",
      "owner": "Putri",
      "expiresOn": "2027-06-01"
    },
    {
      "project": "Onboarding app",
      "market": "TH",
      "team": "QA",
      "purpose": "test account",
      "number": "+66 80 000 0003",
      "provider": "virtual",
      "owner": "Dewi",
      "expiresOn": "2026-10-01"
    },
    {
      "project": "Payments",
      "market": "ID",
      "team": "QA",
      "purpose": "test account",
      "number": "+62 812 0000 0001",
      "provider": "virtual",
      "owner": "Rizky",
      "expiresOn": "2026-11-15"
    },
    {
      "project": "Payments",
      "market": "VN",
      "team": "Support",
      "purpose": "recovery",
      "number": "+84 90 000 0005",
      "provider": "SIM",
      "owner": "Linh"
    }
  ],
  "expiringWithinDays": 7
}
```

# Actor output Schema

## `registry` (type: `string`):

Sorted registry rows with status and duplicate flags (dataset items).

## `summary` (type: `string`):

Counts per status and number of duplicates.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "records": [
        {
            "project": "Onboarding app",
            "market": "ID",
            "team": "QA",
            "purpose": "test account",
            "number": "+62 812 0000 0001",
            "provider": "virtual",
            "owner": "Dewi",
            "expiresOn": "2026-10-30"
        },
        {
            "project": "Onboarding app",
            "market": "ID",
            "team": "Support",
            "purpose": "customer account",
            "number": "+62 812 0000 0002",
            "provider": "SIM",
            "owner": "Putri",
            "expiresOn": "2027-06-01"
        },
        {
            "project": "Onboarding app",
            "market": "TH",
            "team": "QA",
            "purpose": "test account",
            "number": "+66 80 000 0003",
            "provider": "virtual",
            "owner": "Dewi",
            "expiresOn": "2026-10-01"
        },
        {
            "project": "Payments",
            "market": "ID",
            "team": "QA",
            "purpose": "test account",
            "number": "+62 812 0000 0001",
            "provider": "virtual",
            "owner": "Rizky",
            "expiresOn": "2026-11-15"
        },
        {
            "project": "Payments",
            "market": "VN",
            "team": "Support",
            "purpose": "recovery",
            "number": "+84 90 000 0005",
            "provider": "SIM",
            "owner": "Linh"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("nalineerattanaporn/sms-verification-number-registry").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "records": [
        {
            "project": "Onboarding app",
            "market": "ID",
            "team": "QA",
            "purpose": "test account",
            "number": "+62 812 0000 0001",
            "provider": "virtual",
            "owner": "Dewi",
            "expiresOn": "2026-10-30",
        },
        {
            "project": "Onboarding app",
            "market": "ID",
            "team": "Support",
            "purpose": "customer account",
            "number": "+62 812 0000 0002",
            "provider": "SIM",
            "owner": "Putri",
            "expiresOn": "2027-06-01",
        },
        {
            "project": "Onboarding app",
            "market": "TH",
            "team": "QA",
            "purpose": "test account",
            "number": "+66 80 000 0003",
            "provider": "virtual",
            "owner": "Dewi",
            "expiresOn": "2026-10-01",
        },
        {
            "project": "Payments",
            "market": "ID",
            "team": "QA",
            "purpose": "test account",
            "number": "+62 812 0000 0001",
            "provider": "virtual",
            "owner": "Rizky",
            "expiresOn": "2026-11-15",
        },
        {
            "project": "Payments",
            "market": "VN",
            "team": "Support",
            "purpose": "recovery",
            "number": "+84 90 000 0005",
            "provider": "SIM",
            "owner": "Linh",
        },
    ] }

# Run the Actor and wait for it to finish
run = client.actor("nalineerattanaporn/sms-verification-number-registry").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "records": [
    {
      "project": "Onboarding app",
      "market": "ID",
      "team": "QA",
      "purpose": "test account",
      "number": "+62 812 0000 0001",
      "provider": "virtual",
      "owner": "Dewi",
      "expiresOn": "2026-10-30"
    },
    {
      "project": "Onboarding app",
      "market": "ID",
      "team": "Support",
      "purpose": "customer account",
      "number": "+62 812 0000 0002",
      "provider": "SIM",
      "owner": "Putri",
      "expiresOn": "2027-06-01"
    },
    {
      "project": "Onboarding app",
      "market": "TH",
      "team": "QA",
      "purpose": "test account",
      "number": "+66 80 000 0003",
      "provider": "virtual",
      "owner": "Dewi",
      "expiresOn": "2026-10-01"
    },
    {
      "project": "Payments",
      "market": "ID",
      "team": "QA",
      "purpose": "test account",
      "number": "+62 812 0000 0001",
      "provider": "virtual",
      "owner": "Rizky",
      "expiresOn": "2026-11-15"
    },
    {
      "project": "Payments",
      "market": "VN",
      "team": "Support",
      "purpose": "recovery",
      "number": "+84 90 000 0005",
      "provider": "SIM",
      "owner": "Linh"
    }
  ]
}' |
apify call nalineerattanaporn/sms-verification-number-registry --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nalineerattanaporn/sms-verification-number-registry"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/CtsVU4z79sN5NcplJ/builds/bokw5ds1Nabgb6VaN/openapi.json
