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

# Partner-terms consent

> Your end customer accepts our partners' terms themselves on a hosted page — and until they do, virtual bank accounts and pay-outs stay blocked.

Verifying a party proves who they are. It does **not** cover the terms our banking and payment partners require that person to agree to. Those partners insist the real end customer reads and accepts their disclosures on a screen themselves — nobody may accept on their behalf.

So there is one more step, and it belongs to your customer rather than to you: they visit a hosted page and accept each outstanding partner's terms. You can let it surface as a gate after verification, or [collect it up front](#collecting-consent-up-front) before any of their data reaches a partner.

<Warning>
  This is a **gate, not an optional extra**. A party cannot get a [virtual bank account](/guides/finance/virtual-bank-accounts) or receive a [pay-out](/guides/finance/payouts) until its partner-terms consent is complete.
</Warning>

## What you do

Three steps, and the middle one is not yours.

<Steps>
  <Step title="Read the consent state">
    [`GET /parties/{partyId}/partner-terms`](/api-reference/Finance-API/parties/get-a-partys-partner-terms-consent-state) returns one `status` and, while acceptance is outstanding, the `consentUrl`.

    | `status`       | What you do                                                           |
    | -------------- | --------------------------------------------------------------------- |
    | `NOT_REQUIRED` | Nothing — including for a party that hasn't passed KYC yet            |
    | `REQUIRED`     | Hand `consentUrl` to the end customer                                 |
    | `ACCEPTED`     | Nothing — every enabled partner's currently-active terms are accepted |

    The status alone tells you whether a link must be presented. You never need to know which partners are involved or how many — it is one status and one link covering all of them.
  </Step>

  <Step title="Send your customer to the link">
    Present the `consentUrl` — a redirect, an email, wherever your flow puts it. They open it and accept.

    You cannot complete this step for them. That is the entire point of the requirement.
  </Step>

  <Step title="Wait for the status to advance">
    Once acceptance is recorded the status becomes `ACCEPTED` and the URL is no longer returned.

    [Register a webhook](/guides/finance/webhooks) rather than polling.
  </Step>
</Steps>

<Note>
  The party read carries the same state as a cached field, `partnerTermsStatus` on
  [Get party details](/api-reference/Finance-API/parties/get-party-details), if you would rather poll the party you are already fetching. The dedicated endpoint always returns the current link, so it is the one to use when you are about to show a link — a URL you stored earlier may have expired.
</Note>

## Collecting consent up front

The flow above is reactive: you discover consent is needed when a party reaches the gate. You can also get ahead of it.

[`POST /parties/{partyId}/partner-terms/link`](/api-reference/Finance-API/parties/issue-a-partner-terms-consent-link) mints a link immediately, letting your customer accept **every currently-enabled partner's latest terms in one pass — before any of their data is sent to a partner**. That is usually the better experience: consent is collected during your own onboarding rather than surfacing later as a blocker on a pay-out.

<Warning>
  Each call **supersedes the previous link** for that party. A link you already handed out stops working. Never call it to check state — read the consent state for that.
</Warning>

## What the page does

You do not build or host this page — Venly provides it and hands you the link. Two properties of it affect your flow:

* **One page for every outstanding partner.** However many partners a party owes terms to, it is a single link and a single visit. Your customer is never bounced through one page per partner.
* **A separate acceptance per partner.** There is no blanket accept-all, so a customer with several outstanding partners has several things to agree to before the page will let them finish. Expect the visit to take a moment rather than one click.

Each acceptance is recorded individually — who accepted, when, and which version of that partner's terms they saw.

<Note>
  **The terms themselves are not available over the API yet.** Today the hosted page is the only place the
  disclosures are presented — you cannot retrieve their text or render them in your own interface. Exposing the
  terms and conditions through the API is planned for a later phase; until then, hand the customer the link.
</Note>

## It can come back

Consent is not once-and-forever. The requirement re-appears when:

* a **new partner** is added for that party, or
* an existing partner's **terms version changes**.

When that happens the party returns to "acceptance required" with a refreshed link, and the page shows only what is newly outstanding — your customer does not re-accept what they already agreed to.

Treat consent as a state you re-read, not a milestone you record once and forget. A party that was fully onboarded last month can legitimately need another visit.

## Handling the link

| Property        | What it means for you                                                                                              |
| --------------- | ------------------------------------------------------------------------------------------------------------------ |
| **Scoped**      | The link is tied to that party and those terms. It is not a generic page and must not be shared between customers. |
| **Expires**     | An expired link is rejected when opened. Read the party again to get a fresh one rather than caching it.           |
| **Re-issuable** | A fresh link can always be issued for the same party, so an expired or lost link is never a dead end.              |

<Note>
  Because the link expires, fetch it when you are about to show it. A consent URL stored at verification time and used days later will likely be stale.
</Note>

## When the platform is unreachable

The consent state is resolved at request time rather than stored, so the read can fail. It **fails closed**, deliberately:

| HTTP  | `code`                              | Meaning                                                             | Retry?                |
| ----- | ----------------------------------- | ------------------------------------------------------------------- | --------------------- |
| `500` | `identity-verification-rejected`    | The platform refused the request itself                             | **No**                |
| `503` | `identity-verification-unavailable` | Unreachable, or answered but the state could not be resolved safely | **Yes**, with backoff |

A `503` **never** means "nothing outstanding". If the platform reports terms outstanding but no link, you get a `503` rather than a `REQUIRED` you cannot act on — so treating a failure as `NOT_REQUIRED` would skip the gate entirely.

## What this changes for existing integrations

The consent state lives in its **own field**, `partnerTermsStatus` — it is not a new `kycStatus` value. Code that switches on `kycStatus` keeps working unchanged.

What does change is the set of preconditions for money movement. If your integration creates virtual bank accounts or pay-outs, it needs to account for a verified party that is still not ready, and surface the consent link to the customer at that point.

## Next steps

<CardGroup cols={2}>
  <Card title="Onboarding lifecycle" icon="route" href="/guides/finance/onboarding/lifecycle">
    Where consent sits among the other gates.
  </Card>

  <Card title="Account verification" icon="circle-check" href="/guides/finance/kyc-verification">
    KYC and KYB, and what they do and don't cover.
  </Card>

  <Card title="Virtual bank accounts" icon="building-columns" href="/guides/finance/virtual-bank-accounts">
    One of the two flows consent gates.
  </Card>

  <Card title="Pay-outs" icon="money-bill-transfer" href="/guides/finance/payouts">
    The other one.
  </Card>
</CardGroup>
