> ## 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.

# Partner-managed verification

> Submit user profile data and evidence that your verification provider has already verified.

> [!WARNING]
>
> Submit verification evidence is a private endpoint for approved partner integrations. Confirm enablement, accepted
> evidence, and source domains with Payward before sending requests.

Use partner-managed verification when your business has already verified a user and has approval to submit that
verification to Payward. You submit profile data and supporting evidence through separate requests.
Payward makes the final eligibility decision. If you need Payward to collect and verify evidence, see
[Hosted KYC](https://docs.services.payward.com/tabs/developer-documentation/verifications/hosted-kyc.md).

Partner-managed verification supports only countries in the European Economic Area (EEA).

## Integration sequence

**1. Create the user and read requirements**

Create the account using your stable external reference. Read the user's current verification requirements.

**2. Update the profile**

Submit the user's name, date of birth, and residence country through Update verification profile. Collect additional
fields as required by the user's country and onboarding policy.

**3. Submit verification evidence**

Provide each file through an HTTPS URL on an approved source domain. Submit the file source with its verifier
provenance and a UUID idempotency key.

**4. Reconcile status and requirements**

Follow verification notifications and read the latest state. Resolve outstanding requirements. An accepted
submission does not mean onboarding is complete.

## Authenticate and prepare access

Call the PWS API from your backend using `API-Key`, `API-Timestamp`, and `API-Sign`. Follow
[Authentication][authentication] to calculate a fresh signature over each exact request. The signature must match
the body you send, including on retries. Never expose your signing key to browsers or mobile clients.

Payward must approve your integration and the domains used to retrieve evidence. Keep the evidence and verifier
records you need in your own system under your agreed retention policy.

## Create the account and read requirements

Use [Create user][create-user] with your stable `external_reference`. Email is optional.

```json theme={null}
{
  "external_reference": "partner-customer-9001",
  "email": "alex.morgan@example.com"
}
```

Retain the returned `data.id`, for example `AA45N8G4MLDYWAR7`, and use it as `user_id` in subsequent calls.

Call [Get verification requirements][requirements]:

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

Read `state`, `user_action_required`, and the ordered `required_actions`:

| Action | What your integration does |
| - | - |
| `provide_details` | Supply the requested profile details. |
| `verification` | Submit evidence for the requested verification. |
| `wait` | Wait for processing before taking further action. |

Requirements can change after onboarding. Fetch them again after changes and webhook notifications.
Do not treat this guide's examples as a universal list of required fields.

## Update the verification profile

Call [Update verification profile][profile] at `PATCH /v1/users/{user_id}/verifications/profile`.
Supply only the profile fields you want to change.
Omitted fields remain unchanged. Profile completeness is evaluated across onboarding, rather than independently
for each update.

Submit the user's full name, date of birth, and residence country before completing document verification.
Document submissions do not update these profile fields.

The following example collects profile details for a user in Germany:

```json theme={null}
{
  "full_name": {
    "first_name": "Alex",
    "middle_name": "James",
    "last_name": "Morgan"
  },
  "birth": {
    "date": "1990-04-15",
    "city": "Berlin",
    "country": "DE"
  },
  "residence": {
    "line1": "123 Example Street",
    "line2": "Apartment 4B",
    "city": "Berlin",
    "postal_code": "10115",
    "province": "BE",
    "country": "DE"
  },
  "phone": "+4930123456789",
  "nationalities": ["DE"],
  "tax_ids": [
    {
      "id": "12345678901",
      "issuing_country": "DE"
    }
  ],
  "occupation": "computers_and_it",
  "employer_name": "Example Company"
}
```

Save the body as `profile.json`, calculate the request signature, and submit it:

```bash theme={null}
curl -X PATCH "https://api.services.payward.com/v1/users/$USER_ID/verifications/profile" \
  -H "API-Key: $PWS_API_KEY" \
  -H "API-Timestamp: $PWS_API_TIMESTAMP" \
  -H "API-Sign: $PWS_API_SIGN" \
  -H "Content-Type: application/json" \
  --data-binary @profile.json
```

The response acknowledges the update:

```json theme={null}
{
  "data": "success"
}
```

Profile updates do not require an `Idempotency-Key`. Updating verified profile data may
re-trigger identity verification. Read requirements again after the update.

### Field and country requirements

* When you supply `full_name`, include `first_name` and `last_name`.
* When you supply `residence`, include `line1`, `city`, `postal_code`, and `country`.
* Empty `nationalities` and `tax_ids` arrays leave existing values unchanged. You cannot clear them with an empty array.

Use only the fields in [Update verification profile][profile]. The request does not accept `delete_fields` or `terms_acceptance`.

## Provide the files

Provide each file as a source object containing `https_url`. This applies to document fronts and backs, residence
documents, selfies, and `partner_result.response_file`. Host the file on an approved source domain:

```json theme={null}
{
  "https_url": "https://your-allowlisted-bucket.s3.amazonaws.com/passport.jpg"
}
```

The verification processor must be able to retrieve the file without your PWS credentials.
Keep the URL accessible until retrieval completes. A successful submission does not establish that retrieval has completed.
If retrieval fails because the URL expires or becomes inaccessible, make the file available again and submit it with a new key.
Keep the original request unchanged when retrying an uncertain response.

Confirm which formats are accepted for your document or verifier response file with Payward.

## Include verifier provenance

Every evidence submission request requires `partner_result`. Include the result that supports that request:

| Field | Requirement | Meaning |
| - | - | - |
| `verifier` | Required | Identifier of the partner or provider that performed the check. |
| `completed_at` | Required | Date and time when the verifier completed the check. |
| `verifier_reference` | Optional | Reference assigned by the verifier to the check. |
| `response` | Optional | Original JSON object returned by the verifier. |
| `response_file` | Optional | Source object containing the original verifier response file. |

Provide either `response` or `response_file`, never both. You can omit both to submit provenance without the raw
response. Preserve the verifier's own structure when providing an inline response.

## Submit verification evidence

Call [Submit verification evidence][evidence] at `POST /v1/users/{user_id}/verifications/evidence`.
Use a new UUID `Idempotency-Key` for each new submission.
The UUID string must have exactly 36 characters, including hyphens.

| Submission `type` | Evidence fields |
| - | - |
| `identity_document` | `document` with `front` and optional `back` sources. |
| `residence_document` | `address` and `document.source`. |
| `selfie` | `selfie.type` and `selfie.source`. |

### Identity document

Include the document type, number, issuing country, and front source. You can also supply the nationality and
expiration date shown on the document. Include the reverse side when applicable. Omit `back` for passports.

```json theme={null}
{
  "type": "identity_document",
  "document": {
    "type": "passport",
    "number": "X12345678",
    "issuing_country": "DE",
    "front": {
      "https_url": "https://your-allowlisted-bucket.s3.amazonaws.com/passport.jpg"
    }
  },
  "partner_result": {
    "verifier": "partner-verifier",
    "completed_at": "2026-09-21T10:00:00Z"
  }
}
```

Save the body as `document.json` and submit it:

```bash theme={null}
curl -X POST "https://api.services.payward.com/v1/users/$USER_ID/verifications/evidence" \
  -H "API-Key: $PWS_API_KEY" \
  -H "API-Timestamp: $PWS_API_TIMESTAMP" \
  -H "API-Sign: $PWS_API_SIGN" \
  -H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
  -H "Content-Type: application/json" \
  --data-binary @document.json
```

### Residence document

Include `address.line1`, `address.city`, and `address.postal_code` for every supported country.
The residence country comes from the user's profile. You can also supply `address.line2`, `address.province`,
and the document's expiration date when applicable.

```json theme={null}
{
  "type": "residence_document",
  "address": {
    "line1": "123 Example Street",
    "line2": "Apartment 4B",
    "city": "Berlin",
    "province": "BE",
    "postal_code": "10115"
  },
  "document": {
    "type": "residence_certificate",
    "expiration_date": "2027-09-21",
    "source": {
      "https_url": "https://your-allowlisted-bucket.s3.amazonaws.com/residence-certificate.pdf"
    }
  },
  "partner_result": {
    "verifier": "partner-verifier",
    "verifier_reference": "verification-456",
    "completed_at": "2026-09-21T10:00:00Z",
    "response": {
      "status": "approved"
    }
  }
}
```

### Selfie or liveness video

Set `selfie.type` to `image` for a selfie image or `video` for a liveness video that your verifier has already checked.
This example provides HTTPS URLs for the video and the verifier response file:

```json theme={null}
{
  "type": "selfie",
  "selfie": {
    "type": "video",
    "source": {
      "https_url": "https://your-allowlisted-bucket.s3.amazonaws.com/liveness.mp4"
    }
  },
  "partner_result": {
    "verifier": "partner-verifier",
    "verifier_reference": "verification-789",
    "completed_at": "2026-09-21T10:00:00Z",
    "response_file": {
      "https_url": "https://your-allowlisted-bucket.s3.amazonaws.com/selfie-result.json"
    }
  }
}
```

### Read the submission result

A successful evidence submission returns its verification identifier and current lifecycle status:

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

Store the ID against your submission. Acceptance records the evidence for processing; it does not establish that
onboarding is complete.

## Retry evidence submissions

Reuse an idempotency key only when retrying the same submission. Reusing it with different metadata or sources
returns `409` with error code `conflict`. Use a new key when you correct evidence or change a source URL.

For a timeout, lost response, or retryable server error, retain the unchanged body and key.
Calculate fresh API authentication for the retry. Read status and requirements before submitting further evidence.

## Follow status and notifications

Use [Get verification][verification] for a returned ID and [List verifications][verifications] to reconcile attempts.
The lifecycle statuses are `started`, `pending`, `completed`, and `failed`.
A completed verification does not necessarily mean the user is eligible for services.

Read [Get verification requirements][requirements] for the user's current state and required actions.
A `wait` action is non-actionable. Do not treat an empty actionable list as approval or a `closed` user as eligible.

Register notifications through [Create webhook][create-webhook]:

| Notification | Follow-up |
| - | - |
| [`verification.updated`][verification-updated] | Read the referenced verification, then requirements. |
| [`verification.requirements_updated`][requirements-updated] | Read requirements for the referenced user. |
| [`user.disabled`][user-disabled] | Read current requirements and handle the change in eligibility. |
| [`user.closed`][user-closed] | Read current state and stop treating the user as eligible. |

Verify webhook signatures and handle duplicate, delayed, and reordered notifications.
Fetch current state before acting on an event. Poll the read APIs with backoff when notifications are delayed or missed.

## Handle failures

| Failure | Recovery |
| - | - |
| `400`: invalid request | Check required fields, source URLs, and the partner result. Use a new idempotency key if you change the body. |
| `401`: authentication failed | Recalculate the signature over the exact request with a current timestamp. |
| `403`: permission denied | Confirm partner enablement and access with Payward. |
| `404` from Update verification profile | Check the stored user ID. |
| `409` from Submit verification evidence | The key is bound to different metadata or sources. Retry the original submission or use a new key for a changed submission. |
| `429`, `500`, `503`, or `504` | Back off. Retain the same body and key when retrying an evidence submission. |
| `501` from Submit verification evidence | Confirm endpoint availability with Payward. |
| Accepted evidence later fails processing | Read verification details and requirements, then correct the actionable issue. |

Reconcile current requirements and user state before enabling services for a user.

[authentication]: https://docs.services.payward.com/tabs/developer-documentation/get-started/authentication.md

[create-user]: https://docs.services.payward.com/api-reference/sandbox/users/create-user.md

[requirements]: https://docs.services.payward.com/api-reference/sandbox/verifications/get-verification-requirements.md

[profile]: https://docs.services.payward.com/api-reference/sandbox/verifications/update-verification-profile.md

[evidence]: https://docs.services.payward.com/api-reference/sandbox/verifications/submit-verification-evidence.md

[verification]: https://docs.services.payward.com/api-reference/sandbox/verifications/get-verification.md

[verifications]: https://docs.services.payward.com/api-reference/sandbox/verifications/list-verifications.md

[create-webhook]: https://docs.services.payward.com/api-reference/sandbox/webhooks/create-webhook.md

[verification-updated]: https://docs.services.payward.com/api-reference/sandbox/webhooks/verification-updated.md

[requirements-updated]: https://docs.services.payward.com/api-reference/sandbox/webhooks/verification-requirements-updated.md

[user-disabled]: https://docs.services.payward.com/api-reference/sandbox/webhooks/user-disabled.md

[user-closed]: https://docs.services.payward.com/api-reference/sandbox/webhooks/user-closed.md
