> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.dealsignal.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.dealsignal.com/_mcp/server.

# Verification Tiers

> Choose how thoroughly a refresh verifies the profile, work email and phones, and pay only for what is delivered.

Add `verification_tier` to a Contact Profile Refresh Request to choose how thoroughly Dealsignal verifies each profile and its contact details. The response then reports every requested field with its verification status, and you are charged only for what is delivered.

A request with no `verification_tier` works as described in the [Overview](/documentation/contact-profile-refresh-requests/overview).

---

## Choose a tier

|                                                   | `quick`               | `standard`         | `premium`                           |
| ------------------------------------------------- | --------------------- | ------------------ | ----------------------------------- |
| **Profile verified within**                       | 60 days               | 30 days            | 7 days                              |
| **Work email check**                              | Mail server           | Inbox, one pass    | Inbox, several passes               |
| **Email delivered at**                            | `Verified` or `Valid` | `Verified`         | `Verified`                          |
| **`direct_phone`, `mobile_number`**               | Not available         | Validated, no call | Validated, then called              |
| **Phone delivered at**                            | —                     | `Valid` or better  | `Valid` or better                   |
| **`corporate_phone`**                             | Not available         | Returned as stored | Returned as stored, can take longer |
| **Profile that can't be refreshed automatically** | Closed, no charge     | Closed, no charge  | Tried further                       |
| **Typical time**                                  | 1–15 minutes          | 15–60 minutes      | Within 1 business day               |
| **Maximum credits per profile**                   | 0.35                  | 1.50               | 2.50                                |

On `premium`, profiles that refresh automatically are usually ready within an hour.

---

## Send a request

The call is the same as any refresh request, with `verification_tier` at the top level:

```bash
curl -X POST "https://app.dealsignal.com/api/v1/contact_profile_refresh_requests" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "verification_tier": "standard",
    "requested_attributes": [
      { "name": "contact_profile", "priority_order": 0 },
      { "name": "email", "priority_order": 1 },
      { "name": "mobile_number", "priority_order": 2 }
    ],
    "profiles": [
      { "linkedin_url": "https://www.linkedin.com/in/sam-lee-example",
        "company_name": "Acme Corp",
        "metadata": { "crm_record": "003Dn00000AbCdE" } }
    ]
  }'
```

* **Values:** `quick`, `standard`, `premium`. Any other value is rejected with `422` and nothing is created. For a request without a tier, leave `verification_tier` out.
* **Daily limit:** an account can send up to 1,500 profiles a day in requests with a `verification_tier`; test requests don't count. A request that would go over is rejected whole with `422`, for example `Requests with a verification_tier are limited to 1500 profiles a day per account: 1450 sent today, this request has 100.`
* **`requested_attributes`:** `contact_profile`, `email`, `direct_phone`, `mobile_number`, `corporate_phone`. On `quick`, phones are dropped from the request: they are neither returned nor charged.
* **Test mode:** with `test: true` the response has no tier fields and nothing is charged, but your balance must still cover the tier's maximum.
* **Retries:** see [Idempotent requests from Clay](/documentation/contact-profile-refresh-requests/overview#defaults-and-behaviour-notes). To run the same records again with another tier within 15 minutes, use new keys.

Then poll `request_status` as usual. On `standard` and `premium` the result can arrive long after the create call, so a tool that can't poll repeatedly can set a `webhook`: it carries the same fields. A profile can arrive more than once, including one already finished in the create response, so deduplicate on your key in `metadata`. A delivery that fails (anything but a `2xx` within 60 seconds) is retried eight times over about 27 hours, at intervals from 1 minute to 12 hours.

---

## Read the result

Each profile carries these fields next to `custom_columns` and `contact_data`:

| Field             | Description                                                                                                                                                                                                                                                |
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `tier`            | The tier that ran.                                                                                                                                                                                                                                         |
| `delivered`       | `null` while the profile is in progress. `true`: the result is final. `false`: the contact is not delivered and not charged; this is also final.                                                                                                           |
| `delivery_reason` | Why `delivered` is `false` — see [Not delivered](#not-delivered). `null` otherwise.                                                                                                                                                                        |
| `pending_fields`  | Requested fields still being worked on.                                                                                                                                                                                                                    |
| `in_progress`     | Interim values of fields that are not delivered yet: those in `pending_fields`, and a phone that is ready but waits for the email. Each has the `target` status the tier needs (none on `corporate_phone`). Not charged, and they can change or disappear. |
| `credits_charged` | Credits charged for this profile so far. Final once the request's `status` is `completed`.                                                                                                                                                                 |
| `tier_satisfied`  | `true` when the profile is finished and every requested field reached the tier's status or ended `Not Found`. An email that ended `Not Found` reads `tier_satisfied: true` with `delivered: false`, so use `delivered` to decide.                          |

> **Note**
>
> A profile is finished when `delivered` is not `null`. An empty `pending_fields` is not enough: it can also be empty while the profile itself is still being refreshed, for example on a request for `contact_profile` only.

> **Warning**
>
> `contact_data` contains only fields that have reached the requested tier's verification status. `in_progress` is interim and is not suitable for accuracy comparisons or production sends.

While a profile is in progress, `contact_data` shows the profile as currently stored, and each requested field is `null` until it is delivered:

**`In progress`**

```json title="In progress"
{
  "custom_columns": { "linkedin_url": "https://www.linkedin.com/in/sam-lee-example", "company_name": "Acme Corp" },
  "tier": "standard",
  "delivered": null,
  "delivery_reason": null,
  "tier_satisfied": false,
  "credits_charged": 0.0,
  "pending_fields": ["email", "mobile_number"],
  "in_progress": {
    "email": { "value": "sam.lee@acme.example", "status": "Valid", "verified_at": "2026-10-20T09:12:00.000Z", "verification_method": "smtp", "target": "Verified" }
  },
  "contact_data": { "id": 456, "first_name": "Sam", "company_name": "Acme Corp", "...": "…", "email": null, "mobile_number": null }
}
```

**`Delivered`**

```json title="Delivered"
{
  "custom_columns": { "linkedin_url": "https://www.linkedin.com/in/sam-lee-example", "company_name": "Acme Corp" },
  "tier": "standard",
  "delivered": true,
  "delivery_reason": null,
  "tier_satisfied": true,
  "credits_charged": 1.5,
  "pending_fields": [],
  "in_progress": {},
  "contact_data": {
    "id": 456,
    "first_name": "Sam",
    "company_name": "Acme Corp",
    "...": "…",
    "email": { "value": "sam.lee@acme.example", "status": "Verified", "verified_at": "2026-11-02T14:05:00.000Z", "verification_method": "inbox_single" },
    "mobile_number": { "value": "+14155550123", "status": "Valid", "verified_at": "2026-11-02T14:06:00.000Z", "verification_method": "validation_only", "dial_result": null }
  }
}
```

**`Not delivered`**

```json title="Not delivered"
{
  "custom_columns": { "linkedin_url": "https://www.linkedin.com/in/sam-lee-example", "company_name": "Acme Corp" },
  "tier": "standard",
  "delivered": false,
  "delivery_reason": "email_not_found",
  "tier_satisfied": true,
  "credits_charged": 0.0,
  "pending_fields": [],
  "in_progress": {},
  "contact_data": {}
}
```

`response_format=summary` and `response_format=changes` have no tier fields. Use the full format to read them and to tell whether a contact was delivered.

### Field objects

`email`, `mobile_number`, `direct_phone` and `corporate_phone` appear in `contact_data` when requested, next to the 33 profile keys:

| Key                   | Description                                                                                                                                       |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `value`               | The email or phone number. `null` when it is not delivered.                                                                                       |
| `status`              | `Verified`, `Valid`, `Unverified` or `Not Found` — see below.                                                                                     |
| `verified_at`         | When this value was last verified.                                                                                                                |
| `verification_method` | How it was verified — see below. `null` when the value was not checked by one of these methods, on a `Not Found` field, and on `corporate_phone`. |
| `dial_result`         | Phones only: the outcome of the call — see below. `null` when no call was logged.                                                                 |
| `guaranteed`          | `premium` only: `true` when the contact replied to the email or answered the call in person.                                                      |

| `status`     | Email                                                                                                         | Phone                                                                |
| ------------ | ------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- |
| `Verified`   | Passed all the tier's checks.                                                                                 | The call reached the contact or their own voicemail.                 |
| `Valid`      | Found, but not fully verified: treat it as risky, for example on a catch-all domain.                          | The number is valid, but no call confirmed that it is the contact's. |
| `Unverified` | Found, but failed the check, for example the address bounced. `value` is `null`.                              | The number is wrong. `value` is `null`.                              |
| `Not Found`  | Nothing found at this tier's depth, or only a value not verified within the tier's window. `value` is `null`. | Same as for email.                                                   |

| `verification_method` | Meaning                                   |
| --------------------- | ----------------------------------------- |
| `smtp`                | Mail server check.                        |
| `inbox_single`        | Inbox check, one pass.                    |
| `inbox_triple`        | Inbox check, several passes.              |
| `validation_only`     | Number format and carrier check, no call. |
| `dial_ai`             | Automated call.                           |

| `dial_result`                       | `status`     |
| ----------------------------------- | ------------ |
| `Connected to Contact`              | `Verified`   |
| `Voicemail of Contact`              | `Verified`   |
| `Generic Voicemail`                 | `Valid`      |
| `Connected, identity not confirmed` | `Valid`      |
| `Connected, declined to confirm`    | `Valid`      |
| `No Answer`                         | `Valid`      |
| `Wrong Number`                      | `Unverified` |

A phone that is ready waits in `in_progress` until the email finishes, because the contact is delivered only with its email.

`corporate_phone` is company data, returned as stored with its stored status, or as `Not Found`. Tier statuses and windows don't apply to it, and it is not charged. On `premium` it can stay in `pending_fields` while it is being worked on.

### Not delivered

If you request `email`, the contact is delivered only with it. This is decided as soon as the email check ends, even if a phone is still being called. `contact_data` is then `{}` and nothing is charged.

| `delivery_reason`       | Tiers               | What happened                                                                                                                         |
| ----------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `email_not_found`       | All                 | No email verified within the tier's window was found.                                                                                 |
| `email_below_tier`      | All                 | An email was found, but it did not reach the status the tier delivers.                                                                |
| `profile_not_found`     | All                 | The contact's profile could not be found.                                                                                             |
| `profile_outdated`      | `quick`, `standard` | No copy of the profile checked recently enough was available. `premium` may resolve it.                                               |
| `profile_failed`        | `quick`, `standard` | The profile could not be refreshed, for example because there is no usable LinkedIn URL. Retry, or use `premium`.                     |
| `profile_not_refreshed` | `premium`           | The refresh did not succeed, and the stored profile is older than the tier's window.                                                  |
| `no_current_employer`   | All                 | The profile shows no current employer. This one keeps the 33 profile keys in `contact_data`; every requested field reads `Not Found`. |

A request that doesn't ask for `email` is delivered once everything has finished.

### Which job the result describes

On a request with a tier, the email and phones belong to a job the contact holds now: the employer you named in `company_name` if they still work there, otherwise their main current job. `company_name`, `title`, `company_website`, `seniorities` and `departments` describe that job.

The first refresh of a contact for your account can also report a move. When Dealsignal recognises `company_name` as a job the contact has left, `changed_company` reads `true`, and in the [`changes` format](/documentation/contact-profile-refresh-requests/overview#response_formatchanges-and-the-ds_-fields) `ds_baseline_primary_company` names that job. The result is for the current job and charged as usual, or `no_current_employer` if there is none. Any other first refresh follows the rules in the Overview.

---

## Pricing

| Tier       | Profile | + Work email | + Phone                                 | Maximum per profile |
| ---------- | ------- | ------------ | --------------------------------------- | ------------------- |
| `quick`    | 0.25    | 0.10         | Not available                           | 0.35                |
| `standard` | 0.25    | 0.75         | 0.50                                    | 1.50                |
| `premium`  | 0.25    | 1.25         | 1.00 when `Verified`, 0.50 when `Valid` | 2.50                |

* **You pay for what is delivered.** A field is charged only if its value is in `contact_data`.
* **Not charged:** every profile with `delivered: false`, and `corporate_phone` on every tier.
* **One phone price.** `direct_phone` and `mobile_number` are charged once per profile, at the best status among the phones you requested. On `standard`, a phone already confirmed by an earlier call goes out as `Verified` at the same 0.50.
* **Balance check.** The call is rejected with `422` when your balance doesn't cover the maximum for the attributes you request.
* **Every delivered contact is charged,** including contacts you've requested before.

---

## Freshness

The tier's window (60, 30 or 7 days) does two things:

* **Decides what gets refreshed.** A profile last verified inside the window is returned as it is; an older one is refreshed. `contact_refresh_time` overrides this, and `0` refreshes every profile.
* **Decides what can be delivered.** An email or phone is delivered and charged only if it was verified inside the window, counted back from the request's creation. `contact_refresh_time` doesn't change this.