# Verify Users

Phone verification with zero vendor setup

## Navigation

**Getting Started:** [All You Need](/index.md) | [Getting Started](/introduction.md) | [How Sapiom Works](/how-it-works.md) | [Quick Start](/quick-start.md) | [Using Services](/using-services.md) | [For AI Tools](/for-agents.md)  
**Capabilities:** [Overview](/capabilities.md) | **Verify Users** | [Search the Web](/capabilities/search.md) | [AI Model Access](/capabilities/ai-models.md) | [Generate Images](/capabilities/images.md) | [Audio Services](/capabilities/audio.md) | [Browser Automation](/capabilities/browser.md)  
**Integration / Agent Frameworks:** [Overview](/integration/agent-frameworks.md) | [LangChain](/integration/agent-frameworks/langchain.md) | [LangChain Classic](/integration/agent-frameworks/langchain-classic.md)  
**Integration / HTTP Clients:** [Overview](/integration/http-clients.md) | [Axios](/integration/http-clients/axios.md) | [Fetch](/integration/http-clients/fetch.md) | [Node.js HTTP](/integration/http-clients/node-http.md)  
**Governance:** [Overview](/governance.md) | [Setting Up Rules](/governance/rules.md) | [Agents & Identity](/governance/agents.md) | [Activity](/governance/activity.md)  
**Reference / API Reference:** [Introduction](/api-reference/introduction.md)  
**Reference / API Reference / Endpoints:** [Agents Endpoints](/api-reference/endpoints/agents.md) | [Get agent by ID](/api-reference/endpoints/agents/v1-agents-by-id-get.md) | [Update agent](/api-reference/endpoints/agents/v1-agents-by-id-patch.md) | [List all agents](/api-reference/endpoints/agents/v1-agents-get.md) | [Create a new agent](/api-reference/endpoints/agents/v1-agents-post.md) | [API Endpoints](/api-reference/endpoints.md) | [Get Sapiom payment JWKS](/api-reference/endpoints/other/.well-known-sapiom-jwks.json-get.md) | [Analytics Endpoints](/api-reference/endpoints/other.md) | [Get analytics chart](/api-reference/endpoints/other/v1-analytics-chart-get.md) | [Get analytics leaderboards](/api-reference/endpoints/other/v1-analytics-leaderboards-get.md) | [Get analytics summary](/api-reference/endpoints/other/v1-analytics-summary-get.md) | [Rules Endpoints](/api-reference/endpoints/rules.md) | [Get rule by ID](/api-reference/endpoints/rules/v1-spending-rules-by-id-get.md) | [Update a rule](/api-reference/endpoints/rules/v1-spending-rules-by-ruleId-put.md) | [List all rules](/api-reference/endpoints/rules/v1-spending-rules-get.md) | [Create a new rule](/api-reference/endpoints/rules/v1-spending-rules-post.md) | [Transactions Endpoints](/api-reference/endpoints/transactions.md) | [Complete a transaction](/api-reference/endpoints/transactions/v1-transactions-by-transactionId-complete-post.md) | [List transaction costs](/api-reference/endpoints/transactions/v1-transactions-by-transactionId-costs-get.md) | [Add cost to transaction](/api-reference/endpoints/transactions/v1-transactions-by-transactionId-costs-post.md) | [Add facts to transaction](/api-reference/endpoints/transactions/v1-transactions-by-transactionId-facts-post.md) | [Get transaction details](/api-reference/endpoints/transactions/v1-transactions-by-transactionId-get.md) | [Reauthorize a transaction with x402 payment data](/api-reference/endpoints/transactions/v1-transactions-by-transactionId-reauthorize-post.md) | [List transactions](/api-reference/endpoints/transactions/v1-transactions-get.md) | [Create a new transaction](/api-reference/endpoints/transactions/v1-transactions-post.md) | [Verification Endpoints](/api-reference/endpoints/verification.md) | [Check verification code](/api-reference/endpoints/verification/v1-services-verify-check-post.md) | [Send verification code](/api-reference/endpoints/verification/v1-services-verify-send-post.md)  
**Reference / SDK Reference:** [@sapiom/axios](/reference/sdk/axios.md) | [@sapiom/fetch](/reference/sdk/fetch.md) | [SDK Reference](/reference/sdk.md) | [@sapiom/langchain-classic](/reference/sdk/langchain-classic.md) | [@sapiom/langchain](/reference/sdk/langchain.md) | [@sapiom/node-http](/reference/sdk/node-http.md)  
**Reference:** [Concepts](/reference/concepts.md)

---

Verify phone numbers instantly — no Twilio account, no vendor onboarding, just a single API call.

## Quick Example

```typescript

const sapiomFetch = createFetch({
  apiKey: process.env.SAPIOM_API_KEY,
  agentName: "my-agent",
});

const baseUrl = "https://prelude.services.sapiom.ai";

// Step 1: Send a verification code
const sendResponse = await sapiomFetch(`${baseUrl}/verifications`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    target: {
      type: "phone_number",
      value: "+15551234567",
    },
  }),
});

const sendData = await sendResponse.json();
console.log("Verification sent:", sendData.id);

// Step 2: Check the code (after user enters it)
const checkResponse = await sapiomFetch(`${baseUrl}/verifications/check`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    verificationRequestId: sendData.id,
    code: "123456", // code entered by user
  }),
});

const checkData = await checkResponse.json();
console.log("Verified:", checkData.status === "success");
```

## How It Works

When you send a verification request, Sapiom routes it to [Prelude](https://prelude.so), a verification service that handles SMS and email delivery. The SDK automatically handles payment negotiation so you don't need a separate Prelude account.

The verification flow has two steps:

1. **Send a code** — Call the `/verifications` endpoint with a phone number. The user receives a 6-digit code.
2. **Check the code** — When the user enters the code, call `/verifications/check` to verify it. This endpoint is free and rate-limited.

> **Email verification not yet supported:** Email verification (`target.type: "email_address"`) is not yet supported by the upstream provider. Requests with email targets will return a `501 Not Implemented` error. Use phone number verification for now.

Verification codes expire after 10 minutes. If the user doesn't receive the code or it expires, send a new verification request.

## Provider

Powered by [Prelude](https://prelude.so). Prelude handles global SMS delivery with high deliverability and fraud prevention built in.

## API Reference

### Send Verification Code

**Endpoint:** `POST https://prelude.services.sapiom.ai/verifications`

Send a verification code to a phone number.

#### Request

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `target.type` | string | Yes | `phone_number` |
| `target.value` | string | Yes | Phone number in E.164 format |
| `signals` | object | No | Additional signals for fraud detection |
| `options` | object | No | Verification options |
| `metadata` | object | No | Custom metadata to store with request |

**Phone number format:** Use international E.164 format with country code (e.g., `+15551234567` for US, `+442071234567` for UK).

```json
{
  "target": {
    "type": "phone_number",
    "value": "+15551234567"
  }
}
```

#### Response

```json
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "pending"
}
```

Save the `id` — you'll need it to check the code.

#### Send Response Statuses

| Status | Description |
|--------|-------------|
| `pending` | Code sent successfully, awaiting user input |
| `blocked` | Delivery was blocked (rate limiting, fraud prevention, or carrier block). Returns HTTP 429. Your app should handle this — do **not** treat any 200 with an `id` as success. |

### Check Verification Code

**Endpoint:** `POST https://prelude.services.sapiom.ai/verifications/check`

Verify the code entered by the user. This endpoint is free but rate-limited to prevent brute-force attacks.

#### Request

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `verificationRequestId` | string | Yes | The `id` from the send response |
| `code` | string | Yes | 4-8 digit verification code |

```json
{
  "verificationRequestId": "550e8400-e29b-41d4-a716-446655440000",
  "code": "123456"
}
```

#### Response

```json
{
  "id": "660e8400-e29b-41d4-a716-446655440001",
  "status": "success"
}
```

| Status | Description |
|--------|-------------|
| `success` | Code is correct, verification complete |
| `pending` | Verification still in progress |
| `failure` | Code is incorrect |

### Error Codes

| Code | Description |
|------|-------------|
| 400 | Invalid phone number or code format |
| 402 | Payment required — ensure you're using the Sapiom SDK |
| 404 | Verification request not found |
| 410 | Verification code has expired |
| 422 | Invalid verification code (wrong code entered) |
| 429 | Rate limit exceeded or delivery blocked (fraud prevention, carrier block) |
| 501 | Email verification not yet supported — use phone number |

## Complete Example

```typescript

const sapiomFetch = createFetch({
  apiKey: process.env.SAPIOM_API_KEY,
  agentName: "my-agent",
});

const baseUrl = "https://prelude.services.sapiom.ai";

async function verifyPhoneNumber(phoneNumber: string, userCode: string) {
  // Step 1: Send verification code
  const sendResponse = await sapiomFetch(`${baseUrl}/verifications`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      target: {
        type: "phone_number",
        value: phoneNumber,
      },
    }),
  });

  const sendData = await sendResponse.json();
  const verificationId = sendData.id;
  console.log(`Verification code sent to ${phoneNumber}`);

  // Step 2: Check the code (after user enters it)
  const checkResponse = await sapiomFetch(`${baseUrl}/verifications/check`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      verificationRequestId: verificationId,
      code: userCode,
    }),
  });

  const checkData = await checkResponse.json();
  return checkData.status === "success";
}

// Usage
const isVerified = await verifyPhoneNumber("+15551234567", "123456");
console.log("Verified:", isVerified);
```

## Pricing

| Operation | Cost |
|-----------|------|
| Send verification code | $0.015 (1.5 cents) |
| Check verification code | Free |