> ## Documentation Index
> Fetch the complete documentation index at: https://docs.services.payward.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Backend verification API

> Submit end-user verification evidence from your backend and track status with the Payward Verifications API.

Use the backend verification API when your backend already collects KYC evidence and needs Payward to process it. Your backend submits HTTPS evidence URLs and metadata. Payward starts asynchronous verification processing and updates the user's verification state.

This API is similar to [Submit Verification from URL][submit-verification-from-url]. Use [Submit Verification from URL][submit-verification-from-url] when your integration already verified the evidence and Payward should trust the verifier result. Use [Start Verification from URL][start-verification-from-url] when Payward should verify the submitted evidence.

Do not call this API from a browser or mobile client. It uses your API credentials and points to sensitive document evidence.

<Note>
  Backend verification is asynchronous. Treat the start response as confirmation that Payward recorded the verification,
  not as a final verification decision.
</Note>

## How it works

<Steps>
  <Step title="Create or update the user">
    Create the Payward user and provide the profile fields required for onboarding.
  </Step>

  <Step title="Store evidence">
    Store the document or liveness image files behind HTTPS presigned URLs on domains allowlisted for your integration.
  </Step>

  <Step title="Start a backend verification">
    Call [`POST /v1/users/{user_id}/verifications/start/url`][start-verification-from-url] once for each verification
    type you need to submit.
  </Step>

  <Step title="Track status">
    Use [Get verification][get-verification] to fetch one verification by ID, or list attempts with [List
    verifications][list-verifications] until each reaches a terminal status.
  </Step>

  <Step title="Reconcile the user">
    Fetch the user with [Get User][get-user] and use verification failure details according to your integration's
    handling rules.
  </Step>
</Steps>

## Base URL

```text theme={null}
https://api.services.payward.com
```

## Authentication

All requests require three headers:

| Header      | Description                                   |
| ----------- | --------------------------------------------- |
| `API-Key`   | Your public API key                           |
| `API-Nonce` | Monotonically increasing integer nonce        |
| `API-Sign`  | HMAC signature computed with your private key |

See [Authentication](/tabs/developer-documentation/get-started/authentication) for how to generate the signature.

## Step 1 - Create or update the user

Before starting backend verification, create the user and provide the profile fields required for onboarding.

Use these endpoints before starting verification:

| Endpoint                                   | Use it to                  |
| ------------------------------------------ | -------------------------- |
| [`POST /v1/users`][create-user]            | Create a user              |
| [`PATCH /v1/users/{user_id}`][update-user] | Update an existing user    |
| [`GET /v1/users/{user_id}`][get-user]      | Read the latest user state |

Store the user ID. [Start Verification from URL][start-verification-from-url] uses it as the `user_id` path parameter.

## Step 2 - Store evidence

Store files behind HTTPS presigned URLs on domains allowlisted for your Payward integration. Evidence URL fields must use `https://` URLs.

Accepted evidence depends on the verification type:

| Start `type`         | Status `types` value | Required file fields                      | Description                                |
| -------------------- | -------------------- | ----------------------------------------- | ------------------------------------------ |
| `identity_document`  | `proof_of_identity`  | `front_url`, optional `back_url`          | Government identity document verification  |
| `residence_document` | `proof_of_address`   | `document_url`                            | Residence or address document verification |
| `liveness`           | `proof_of_liveness`  | `left_url`, `center_url`, and `right_url` | Three-point liveness image verification    |

Status responses report document roles in `types` and the evidence collection channel in `method`. Backend URL submissions use `method: "url"` and include one value in `types`.

The start request does not include `verifier`, `verified_at`, `verifier_response`, or `verifier_response_url`. Those fields belong to [Submit Verification from URL][submit-verification-from-url] because that endpoint trusts a verifier result supplied by your integration.

## Step 3 - Start a backend verification

Submit one verification per [Start Verification from URL][start-verification-from-url] request:

```text theme={null}
POST /v1/users/{user_id}/verifications/start/url
```

The request body uses a `type` discriminator.

### Identity document

```bash theme={null}
curl -X POST "https://api.services.payward.com/v1/users/$USER_ID/verifications/start/url" \
  -H "API-Key: $PWS_API_KEY" \
  -H "API-Nonce: $PWS_API_NONCE" \
  -H "API-Sign: $PWS_API_SIGN" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "identity_document",
    "metadata": {
      "identity": {
        "full_name": {
          "first_name": "Alex",
          "last_name": "Morgan"
        },
        "birth": {
          "date": "1990-01-31"
        }
      },
      "document_type": "passport",
      "document_number": "A1234567",
      "issuing_country": "US"
    },
    "front_url": "https://your-allowlisted-bucket.s3.amazonaws.com/front.png?X-Amz-Algorithm=AWS4-HMAC-SHA256"
  }'
```

### Residence document

```json theme={null}
{
  "type": "residence_document",
  "metadata": {
    "address": {
      "line1": "800 Market Street",
      "line2": "Suite 210",
      "city": "San Francisco",
      "postal_code": "94102",
      "province": "CA",
      "country": "US"
    },
    "document_type": "utility_bill"
  },
  "document_url": "https://your-allowlisted-bucket.s3.amazonaws.com/address.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256"
}
```

### Liveness

```json theme={null}
{
  "type": "liveness",
  "left_url": "https://your-allowlisted-bucket.s3.amazonaws.com/liveness-left.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256",
  "center_url": "https://your-allowlisted-bucket.s3.amazonaws.com/liveness-center.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256",
  "right_url": "https://your-allowlisted-bucket.s3.amazonaws.com/liveness-right.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256"
}
```

A successful response returns the public verification ID:

```json theme={null}
{
  "data": {
    "verification_id": "PVABCDE-FGHIJ-KLMNOP"
  }
}
```

Store `verification_id`. You need it for reconciliation and support.

## Step 4 - Track status

Use [`GET /v1/users/{user_id}/verifications/{verification_id}`][get-verification] to fetch the latest state for one verification:

```bash theme={null}
curl -X GET "https://api.services.payward.com/v1/users/$USER_ID/verifications/$VERIFICATION_ID" \
  -H "API-Key: $PWS_API_KEY" \
  -H "API-Nonce: $PWS_API_NONCE" \
  -H "API-Sign: $PWS_API_SIGN"
```

If you do not have the verification ID, use [`GET /v1/users/{user_id}/verifications`][list-verifications]:

```bash theme={null}
curl -X GET "https://api.services.payward.com/v1/users/$USER_ID/verifications" \
  -H "API-Key: $PWS_API_KEY" \
  -H "API-Nonce: $PWS_API_NONCE" \
  -H "API-Sign: $PWS_API_SIGN"
```

`verifications` is returned in reverse chronological order.

Example status response:

```json theme={null}
{
  "data": {
    "verification_id": "PVABCDE-FGHIJ-KLMNOP",
    "types": ["proof_of_liveness"],
    "method": "url",
    "status": "pending",
    "created_at": "2026-05-20T14:30:00Z",
    "updated_at": "2026-05-20T14:45:00Z"
  }
}
```

## Statuses

| Status      | What it means                                            | What to do                                                                 |
| ----------- | -------------------------------------------------------- | -------------------------------------------------------------------------- |
| `started`   | Payward recorded the verification and started processing | Wait for an update                                                         |
| `pending`   | The verification is waiting on asynchronous review       | Wait for an update                                                         |
| `completed` | The verification finished successfully                   | Fetch the user and confirm the final user status before enabling activity  |
| `failed`    | The verification reached a terminal failure state        | Fetch the user and verification state to determine the next available step |

## Failure reasons

Failure reasons use this shape:

```json theme={null}
{
  "code": "expired",
  "details": ["Document expired before submission."]
}
```

Treat `code` as informational unless your Payward integration defines specific handling. Display `details`, but do not parse or branch on it.

## API reference

| Endpoint                                                                          | Reference                                                  |
| --------------------------------------------------------------------------------- | ---------------------------------------------------------- |
| [`POST /v1/users/{user_id}/verifications/start/url`][start-verification-from-url] | [Start verification from URL][start-verification-from-url] |
| [`GET /v1/users/{user_id}/verifications/{verification_id}`][get-verification]     | [Get verification][get-verification]                       |
| [`GET /v1/users/{user_id}/verifications`][list-verifications]                     | [List verifications][list-verifications]                   |

[create-user]: /api-reference/users/create-user

[get-user]: /api-reference/users/get-user

[get-verification]: /api-reference/verifications/get-verification

[list-verifications]: /api-reference/verifications/list-verifications

[start-verification-from-url]: /api-reference/verifications/start-verification-from-url

[submit-verification-from-url]: /api-reference/verifications/submit-verification-from-url

[update-user]: /api-reference/users/update-user
