# Profile status

> Check if a person profile exists in the database before requesting enrichment.

## Introduction

The Person Profile Status endpoint verifies whether a person profile exists in our database and returns freshness information. Use it to check data availability **before** spending credits on a full fetch or a live pull.

## When to use

A typical cost-optimized workflow looks like this:

1. **Call Profile Status:** get existence status, last update date, and content counts (experience, skills, education).
2. **If the profile exists and is recent:** use [Profile](https://docs.reversecontact.com/endpoints/fetch-profile) (cached, 1 credit) to retrieve the full enriched data.
3. **If the profile is stale or missing:** use [Profile live](https://docs.reversecontact.com/endpoints/fetch-profile-live) (fresh from Social, 2 credits) for an up-to-date result.

This simple check → fetch/live decision can save significant credits at scale.

> [!NOTE]
> Profile Status is free, but it still requires a non-empty credit balance. When your workspace reaches 0 credits it returns `402 NO_CREDITS` (top up to resume), since no fetch or live pull could follow anyway.

## Authorization

| Name     | Type   | Required | Description                                                                                         |
| -------- | ------ | -------- | --------------------------------------------------------------------------------------------------- |
| `apikey` | string | Yes      | Your API key from the developer dashboard. Pass it via `Authorization: Bearer YOUR_API_KEY` header. |

## Request body

Provide **either** `url` or `id`. If both are supplied, `id` takes precedence.

| Name  | Type   | Required    | Description                                                                                                              |
| ----- | ------ | ----------- | ----------------------------------------------------------------------------------------------------------------------- |
| `url` | string | Conditional | Public Social profile URL (e.g. `https://social.com/in/janedoe`). Required unless `id` is given.                        |
| `id`  | string | Conditional | ReverseContact person id from a previous response (e.g. `prs_01jbd5vewyenebxgaz869ffe5t`). Required unless `url` is given. |

## Response structure

| Field     | Type    | Description                                      |
| --------- | ------- | ------------------------------------------------ |
| `success` | boolean | `true` if the request was processed successfully |
| `error`   | `null`  | Always `null` on success                         |

**data** (CheckData): Availability and freshness information (`null` on error responses)

| Field             | Type           | Description                                                                                              |
| ----------------- | -------------- | -------------------------------------------------------------------------------------------------------- |
| `exists`          | boolean        | `true` if the profile exists in the database                                                             |
| `lastUpdate`      | string \| null | When ReverseContact last fetched this profile from the source (ISO 8601). `null` when `exists` is `false` |
| `experienceCount` | number         | Number of experience entries. Only present when `exists` is `true`                                       |
| `skillCount`      | number         | Number of skills. Only present when `exists` is `true`                                                   |
| `schoolCount`     | number         | Number of education entries. Only present when `exists` is `true`                                        |

**quotas** (V2QuotaInfo): Credits and rate limit usage after this request

| Field             | Type   | Description                                                                                    |
| ----------------- | ------ | ---------------------------------------------------------------------------------------------- |
| `creditsConsumed` | number | Credits consumed by this request. Always `0` for Profile Status                                |

**workspace** (Workspace): Workspace-level limits

| Field                 | Type    | Description                                    |
| --------------------- | ------- | ---------------------------------------------- |
| `id`                  | string  | Your workspace identifier                      |
| `hasUnlimitedCredits` | boolean | Whether workspace credits are unlimited        |
| `allowDailyOvercost`  | boolean | Whether the workspace may exceed its daily cap |

**credits** (Credits): Credit balance

| Field   | Type   | Description                |
| ------- | ------ | -------------------------- |
| `total` | number | Total credits in your plan |
| `used`  | number | Credits consumed so far    |
| `left`  | number | Remaining credits          |

**dailyLimit** (DailyLimit): Daily request limit (`null` if not configured)

| Field       | Type   | Description                             |
| ----------- | ------ | --------------------------------------- |
| `limit`     | number | Maximum requests per day                |
| `used`      | number | Requests made today                     |
| `left`      | number | Remaining requests today                |
| `nextReset` | string | When the daily window resets (ISO 8601) |

**minuteRateLimit** (MinuteRateLimit): Per-minute rate limit

| Field       | Type   | Description                              |
| ----------- | ------ | ---------------------------------------- |
| `limit`     | number | Maximum requests per minute              |
| `used`      | number | Requests made in the current minute      |
| `left`      | number | Remaining requests in the current minute |
| `nextReset` | string | When the minute window resets (ISO 8601) |

**key** (ApiKey): API key-level limits (`null` when request is from dashboard)

| Field | Type   | Description        |
| ----- | ------ | ------------------ |
| `id`  | string | API key identifier |

**dailyLimit** (KeyDailyLimit): Daily limit for this key (`null` if not configured)

| Field       | Type   | Description                             |
| ----------- | ------ | --------------------------------------- |
| `limit`     | number | Maximum requests per day                |
| `used`      | number | Requests made today                     |
| `left`      | number | Remaining requests today                |
| `nextReset` | string | When the daily window resets (ISO 8601) |

**minuteRateLimit** (KeyMinuteRateLimit): Minute rate limit for this key

| Field       | Type   | Description                              |
| ----------- | ------ | ---------------------------------------- |
| `limit`     | number | Maximum requests per minute              |
| `used`      | number | Requests made in the current minute      |
| `left`      | number | Remaining requests in the current minute |
| `nextReset` | string | When the minute window resets (ISO 8601) |

**metadata** (V2ResponseMetadata): Request tracking information

| Field             | Type   | Description                          |
| ----------------- | ------ | ------------------------------------ |
| `requestId`       | string | Unique identifier for this request   |
| `executionTimeMs` | number | Total execution time in milliseconds |

## Code examples

**Code Examples**

```bash [cURL]
curl -X POST https://api.reversecontact.com/v2/fetch/persons/check \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://social.com/in/janedoe"}'
```
```javascript [JavaScript]
const response = await fetch("https://api.reversecontact.com/v2/fetch/persons/check", {
  method: "POST",
  headers: {
    "Authorization": "Bearer YOUR_API_KEY",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    url: "https://social.com/in/janedoe"
  })
});

const data = await response.json();
if (data.data.exists) {
  console.log(`Profile exists, last updated ${data.data.lastUpdate}`);
} else {
  console.log("Profile not in database yet");
}
```
```python [Python]
import requests

response = requests.post(
    "https://api.reversecontact.com/v2/fetch/persons/check",
    headers={
        "Authorization": "Bearer YOUR_API_KEY",
        "Content-Type": "application/json"
    },
    json={"url": "https://social.com/in/janedoe"}
)

data = response.json()
if data["data"]["exists"]:
    print(f"Profile exists, last updated {data['data']['lastUpdate']}")
else:
    print("Profile not in database yet")
```

## Example response

**Example Response**

```json [200 - Found]
{
  "success": true,
  "data": {
    "exists": true,
    "lastUpdate": "2025-01-15T09:30:00.000Z",
    "experienceCount": 5,
    "skillCount": 12,
    "schoolCount": 2
  },
  "error": null,
  "metadata": {
    "requestId": "req_c1d2e3f4g5h6",
    "executionTimeMs": 120
  },
  "quotas": {
    "creditsConsumed": 0,
    "workspace": {
      "id": "ws_abc123",
      "credits": {
        "total": 10000,
        "used": 4521,
        "left": 5479
      },
      "dailyLimit": null,
      "minuteRateLimit": {
        "limit": 60,
        "used": 12,
        "left": 48,
        "nextReset": "2025-01-15T09:31:00.000Z"
      },
      "hasUnlimitedCredits": false,
      "allowDailyOvercost": false
    },
    "key": {
      "id": "key_abc123",
      "dailyLimit": null,
      "minuteRateLimit": {
        "limit": 60,
        "used": 12,
        "left": 48,
        "nextReset": "2025-01-15T09:31:00.000Z"
      }
    }
  }
}
```
```json [200 - Not Found]
{
  "success": true,
  "data": {
    "exists": false,
    "lastUpdate": null
  },
  "error": null,
  "metadata": {
    "requestId": "req_d4e5f6g7h8i9",
    "executionTimeMs": 85
  },
  "quotas": {
    "creditsConsumed": 0,
    "workspace": {
      "id": "ws_abc123",
      "credits": {
        "total": 10000,
        "used": 4521,
        "left": 5479
      },
      "dailyLimit": null,
      "minuteRateLimit": {
        "limit": 60,
        "used": 13,
        "left": 47,
        "nextReset": "2025-01-15T09:31:00.000Z"
      },
      "hasUnlimitedCredits": false,
      "allowDailyOvercost": false
    },
    "key": {
      "id": "key_abc123",
      "dailyLimit": null,
      "minuteRateLimit": {
        "limit": 60,
        "used": 13,
        "left": 47,
        "nextReset": "2025-01-15T09:31:00.000Z"
      }
    }
  }
}
```
