> For the complete documentation index, see [llms.txt](https://docs.idlayr.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.idlayr.com/products/number-verification/reverse-sms/integration.md).

# Integration

{% hint style="info" %}
**Backend API** · Early Access
{% endhint %}

Reverse SMS is integrated **entirely from your backend**, plus a small client-side step that opens the user's native SMS composer via a URL scheme. **There is no IDlayr SDK to install** — the device-side action is a standard `sms:` deep link your app constructs from data your backend supplies.

The flow:

1. Your backend mints an access token.
2. Your backend creates a check and receives the SMS routing details (destination MSISDN + message body).
3. Your backend passes those details to your app.
4. Your app opens the native SMS composer pre-filled with the destination and body. The user taps Send.
5. Your backend receives the verification result via callback or polling.

## 1. Mint an access token

```bash
curl -X POST https://{data_residency}.api.idlayr.com/oauth2/token \
  -u "{client_id}:{client_secret}" \
  -d "grant_type=client_credentials" \
  -d "scope=reverse_sms"
```

Response:

```json
{
  "access_token": "...",
  "token_type": "bearer",
  "expires_in": 3600,
  "scope": "reverse_sms"
}
```

See [Authentication](/get-started/authentication.md).

## 2. Create the check

POST the user's phone number to create a Reverse SMS check.

```bash
curl -X POST https://{data_residency}.api.idlayr.com/v1/number-verification/reverse-sms-checks \
  -H "Authorization: Bearer {access_token}" \
  -H "Content-Type: application/json" \
  -d '{
    "phone_number": "+447700900000",
    "callback_url": "https://your.app/callbacks/reverse-sms"
  }'
```

Request fields:

* `phone_number` — the MSISDN to verify, in E.164.
* `callback_url` *(optional)* — receives the terminal-status notification when the check reaches `COMPLETED`, `EXPIRED`, or `ERROR`.
* `reference_id` *(optional)* — your own identifier, echoed back on responses and any callback.

Response includes:

* `check_id` — used for correlation.
* The **SMS routing details** the device will use to send the verification SMS — a destination MSISDN (an IDlayr-provisioned number) and a message body (an opaque correlation token).
* `status` — initially `ACCEPTED`.
* `ttl` — seconds until the check expires if no SMS is received.

## 3. Hand the SMS routing details to your app

Pass the destination MSISDN, message body, and `check_id` from your backend to your iOS or Android app over your existing API channel. No specific transport is required — these are just two strings.

## 4. Open the native SMS composer on the device

Your app constructs an `sms:` URL with the destination and body, and asks the OS to open it. This launches the platform's native SMS app pre-filled. The user reviews the message and taps Send.

**iOS**

```swift
guard let body = body.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed),
      let url = URL(string: "sms:\(destination)&body=\(body)") else { return }
UIApplication.shared.open(url)
```

**Android**

```kotlin
val intent = Intent(Intent.ACTION_VIEW).apply {
    data = Uri.parse("sms:$destination")
    putExtra("sms_body", body)
}
startActivity(intent)
```

{% hint style="warning" %}
**The user must tap Send.** Both Apple and Android require user confirmation for outbound SMS — apps cannot silently dispatch SMS without elevated platform privileges that ordinary apps don't have, and don't need for this flow.
{% endhint %}

Your app doesn't need any IDlayr-specific permissions, SDK, or platform code. The `sms:` URL scheme is standard on both platforms.

## 5. Receive the result

The user tapping Send doesn't directly notify your backend — the carrier delivers the SMS to IDlayr, IDlayr verifies it, and **your backend** learns the outcome.

**Callback** (recommended):

If you supplied a `callback_url` in step 2, IDlayr POSTs the terminal-state ReverseSMSCheck to it when the SMS is received and verified, or when the check expires. The callback payload contains `match` and `status`. See [Callbacks](/products/number-verification/reverse-sms/callbacks.md).

**Polling**:

```bash
curl https://{data_residency}.api.idlayr.com/v1/number-verification/reverse-sms-checks/{check_id} \
  -H "Authorization: Bearer {access_token}"
```

Poll until `status` is no longer `ACCEPTED`. The TTL on the check bounds how long this can take.

## Production patterns

* **Cache access tokens** until they expire. Don't mint a fresh token per request.
* **Trust the backend, not the app.** A user tapping Send doesn't confirm that IDlayr received the SMS. Wait for the callback or poll for the resolved check.
* **Surface a "didn't send the SMS?" branch.** Users can cancel the SMS composer; the check then sits in `ACCEPTED` until TTL. Your UX should offer a fallback path (resend, alternative verification) after a reasonable wait.
* **Sandbox vs production**: same endpoint, different project. Sandbox simulates the carrier-side delivery without sending real SMS — your app code is unchanged. See [Testing in sandbox](/products/number-verification/reverse-sms/testing.md).
* **Carrier-side delivery delay**: SMS isn't instant. Allow at least 10–30 seconds before assuming the SMS failed.
* **Verify callback signatures**: never trust a callback payload before verifying the JWKS signature.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.idlayr.com/products/number-verification/reverse-sms/integration.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
