---
title: "Add a KYC Agreement"
method: POST
path: "/agreements/kyc"
tags: ["Agreements"]
---

# Add a KYC Agreement

`POST /agreements/kyc`

Create an Agreement against a KYC-trusted account holder's bank account.

The calling account must be flagged as `kyc_trusted`. If it is not, a
`400 Bad Request` will be returned with `must_be_kyc_trusted`.

When the optional bank connection attributes (`basiq_user_id`,
`basiq_connection_id`, `proviso_reference`, `credit_sense_app_id`) are
provided, the Agreement is created in the `unverified` state and bank
connection verification is queued asynchronously. When verification
succeeds the Agreement transitions to `accepted`; when it fails the
Agreement transitions to `declined` and the failure reason is recorded
on `status_reason`. The verification outcome is not reflected in this
endpoint's response - listen for the corresponding `agreement.accepted`
or `agreement.declined` webhook to observe the final state.

When no bank connection attributes are provided, the Agreement is
auto-accepted before the response is returned.

## Headers

- `Zepto-API-Version` string

## Request body

- AddKYCAgreementRequest
  - `authoriser` Authoriser, required
    - `name` string, required — The authoriser's full name.
    - `email` string, email, required — The authoriser's email address.
    - `metadata` object — Custom keyed data attached to the resulting Contact for the authoriser.
    - `bank_account` AuthoriserBankAccount, required
      - `account_number` string, required — The authoriser's bank account number. Must contain digits only.
      - `branch_code` string, required — The 6-digit BSB for the authoriser's bank account (no hyphen).
      - `basiq_user_id` string — Optional Basiq user ID. When supplied alongside `basiq_connection_id`, the Agreement is created in `unverified` state and bank connection verification is queued.
      - `basiq_connection_id` string — Optional Basiq connection ID. See `basiq_user_id`.
      - `proviso_reference` string — Optional Proviso reference. When supplied, the Agreement is created in `unverified` state and bank connection verification is queued.
      - `credit_sense_app_id` string — Optional CreditSense application ID. When supplied, the Agreement is created in `unverified` state and bank connection verification is queued.
  - `terms` Terms, required
    - `per_payout` PerPayout, required — Per-payout limits. Both `min_amount` and `max_amount` keys must be present; set either to `null` for no limit.
      - `min_amount` integer, nullable, required — Minimum amount in cents a Payment Request can be in order to be auto-approved. Specify `null` for no limit.
      - `max_amount` integer, nullable, required — Maximum amount in cents a Payment Request can be in order to be auto-approved. Specify `null` for no limit.
    - `per_frequency` PerFrequency, required — Frequency window limits. Both `days` and `max_amount` keys must be present; set either to `null` for no limit. When `max_amount` is set, `days` must also be set.
      - `days` integer, nullable, required — Number of days the frequency window covers. Specify `null` for no limit.
      - `max_amount` integer, nullable, required — Maximum aggregate amount in cents across all Payment Requests within the frequency window. Specify `null` for no limit.
    - `access_balance` boolean — When true, the Agreement allows balance access for the authoriser.
  - `metadata` object — Your custom keyed data attached to the Agreement.

## Response `200`

OK

- AddKYCAgreementResponse
  - `data` object, required
    - `ref` string, required — The Agreement reference (Min: 3 - Max: 18)
    - `initiator_id` string, uuid, required — Your Zepto account ID
    - `authoriser_id` string, uuid, required — The authoriser's account ID (AnyoneAccount)
    - `contact_id` string, uuid, required — The Contact ID representing the authoriser within Zepto
    - `bank_account_id` string, uuid, required — The authoriser's bank account ID
    - `status` 'accepted' | 'unverified', required — The status of the Agreement immediately after creation. `accepted` when no bank connection attributes were supplied; `unverified` when bank connection attributes were supplied (later transitions to `accepted` or `declined` asynchronously depending on the verification outcome).
    - `status_reason` string, nullable, required — Free text reason for the current status. Always `null` in this response; populated with the verification failure reason if the Agreement later transitions to `declined`.
    - `responded_at` string, date-time, nullable, required — The date-time when the Agreement status was set.
    - `created_at` string, date-time, required — The date-time when the Agreement was created.
    - `terms` Terms, required
      - `per_payout` PerPayout, required — Per-payout limits. Both `min_amount` and `max_amount` keys must be present; set either to `null` for no limit.
        - `min_amount` integer, nullable, required — Minimum amount in cents a Payment Request can be in order to be auto-approved. Specify `null` for no limit.
        - `max_amount` integer, nullable, required — Maximum amount in cents a Payment Request can be in order to be auto-approved. Specify `null` for no limit.
      - `per_frequency` PerFrequency, required — Frequency window limits. Both `days` and `max_amount` keys must be present; set either to `null` for no limit. When `max_amount` is set, `days` must also be set.
        - `days` integer, nullable, required — Number of days the frequency window covers. Specify `null` for no limit.
        - `max_amount` integer, nullable, required — Maximum aggregate amount in cents across all Payment Requests within the frequency window. Specify `null` for no limit.
      - `access_balance` boolean — When true, the Agreement allows balance access for the authoriser.
    - `metadata` object — Your custom keyed data. Omitted when no metadata is set.
    - `open_agreement_id` string, uuid, nullable — Always `null` for this endpoint - reserved for Agreements created via the Open Agreements flow.

## Other responses

- `400` — Bad Request (errors)
- `401` — Unauthorized - missing or invalid bearer token
- `403` — Forbidden - the caller does not have permission to create this resource

---

[API](https://skmtc.net/zeptopayments/apis/zepto-api.md) · [All operations](https://skmtc.net/zeptopayments/apis/zepto-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/zeptopayments/zepto-api/revisions/6353e9b9af6f/schema)
