Individual Payout Limits

Overview

An individual customer starts with the corridor's default payout limits. Read them at any time, and ask for higher ones when the customer needs more headroom. A business customer has no equivalent flow.

GET /limits ──▶ collect risk profile + documents ──▶ POST /limit-requests ──▶ review ──▶ REVIEWED ──▶ GET /limits

The four steps

  1. Read the current limits — what the ceilings are now, and how much is left.
  2. Supply the risk profile — the customer's occupation, employment, and funding details.
  3. Upload the supporting documents — evidence of where the funds come from.
  4. Submit the request and track the review — the review completes asynchronously.

What to know before you start

  • This applies to INDIVIDUAL customers only. A BUSINESS customer gets 400 VALIDATION_ERROR on a limit request, and an empty limits list.
  • The customer must already be onboarded and ACTIVE at the corridor. Check onboarding[].status on GET /v1/payments/customers/{customer_id} first.
  • Only one request can be open at a time. Submitting again while one is under review returns the open request unchanged.
  • A completed review reports the limits in effect afterwards, not an approve/decline decision. The limits can come back unchanged, so compare them against the read you took before requesting.


1. Read the current limits

GET /v1/payments/customers/{customer_id}/limits

curl https://api-staging.checker.finance/v1/payments/customers/cus_01ARZ3NDEKTSV4RRFFQ69G5KYC/limits \
  -H "X-Api-Key: $API_KEY" \
  -H "X-Timestamp: $TIMESTAMP" \
  -H "X-Nonce: $(uuidgen)" \
  -H "X-Signature: $SIGNATURE"

Response — 200 OK:

{
  "data": [
    {
      "provider": "provider-a",
      "limits": [
        {
          "type": "WITHDRAWAL",
          "period": "DAILY",
          "currency": "USD",
          "limit": "10000.00",
          "used": "250.00",
          "remaining": "9750.00"
        },
        {
          "type": "WITHDRAWAL",
          "period": "ROLLING_30D",
          "currency": "USD",
          "limit": "50000.00",
          "used": "250.00",
          "remaining": "49750.00"
        }
      ]
    }
  ]
}
FieldMeaning
typeThe operation the limit constrains.
periodThe window the limit is measured over — DAILY or ROLLING_30D.
limitThe ceiling for that window.
usedConsumed so far in the current window.
remaininglimit − used: the headroom a payout can use right now.

Notes:

  • An empty data array means there is no limits-capable corridor for this customer yet — a business customer, or an individual still onboarding.
  • Add ?provider=provider-a to read one corridor. Unlike the default read, this is strict: an unknown identifier returns 400 PROVIDER_NOT_AVAILABLE, and a corridor that does not review limits returns 422 OPERATION_NOT_SUPPORTED.
  • An unknown customer_id returns 404 NOT_FOUND.


2. Supply the risk profile

Higher limits need a fuller picture of the customer than onboarding collects. Send it as kyc.risk_profile, either on the customer record now or inline on the request in step 4.

PATCH /v1/payments/customers/{customer_id}

curl -X PATCH https://api-staging.checker.finance/v1/payments/customers/cus_01ARZ3NDEKTSV4RRFFQ69G5KYC \
  -H "X-Api-Key: $API_KEY" \
  -H "X-Timestamp: $TIMESTAMP" \
  -H "X-Nonce: $(uuidgen)" \
  -H "X-Signature: $SIGNATURE" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "kyc": {
      "risk_profile": {
        "occupation": "SOFTWARE_DEVELOPER",
        "employment_status": "EMPLOYED",
        "source_of_funds": ["EMPLOYMENT_INCOME", "PERSONAL_SAVINGS"],
        "purpose_of_account": ["SALARY_AND_INCOME_RECEIPT", "PERSONAL_EXPENSES"],
        "anticipated_monthly_activity": "UNDER_100K"
      }
    }
  }'

All five fields are required. A partial profile is treated as no profile at all, so the request in step 4 returns 422 MISSING_KYC_FIELDS naming whichever are absent.

FieldValues
occupationA closed list of occupation titles, e.g. SOFTWARE_DEVELOPER, ACCOUNTANT_AUDITOR, REGISTERED_NURSE, PHYSICIAN, LAWYER, UNIVERSITY_PROFESSOR, AIRCRAFT_PILOT, CARPENTER, SALES_REPRESENTATIVE, UNEMPLOYED_NO_WORK_5_YEARS. See the Occupation schema in the API reference for the full set.
employment_statusEMPLOYED, SELF_EMPLOYED, RETIRED, STUDENT, UNEMPLOYED
purpose_of_accountOne or more of SALARY_AND_INCOME_RECEIPT, PERSONAL_EXPENSES, FAMILY_SUPPORT, BUSINESS_OPERATIONS, PURCHASE_GOODS_AND_SERVICES, RECEIVE_PAYMENTS_FOR_GOODS_AND_SERVICES, ECOMMERCE_PAYMENTS, INVESTMENT_PURPOSES, OTHER
source_of_fundsOne or more of EMPLOYMENT_INCOME, PERSONAL_SAVINGS, GOVERNMENT_BENEFITS, BUSINESS_INCOME, PENSION_RETIREMENT, INVESTMENT_PROCEEDS, SALE_OF_ASSETS, SALES_OF_GOODS_AND_SERVICES
anticipated_monthly_activityExpected monthly volume in USD: UNDER_100K, 100K_TO_1M, 1M_TO_10M, 10M_TO_50M, 50M_TO_250M, OVER_250M

Notes:

  • The profile holds no sensitive identifiers, so every field is returned on GET /v1/payments/customers/{customer_id}. Re-PATCH it at any time to correct a value.


3. Upload the supporting documents

A limit review needs evidence of where the money comes from, and an address confirmation recent enough to support the higher ceiling. Upload each file separately.

POST /v1/payments/customers/{customer_id}/upload

curl -X POST https://api-staging.checker.finance/v1/payments/customers/cus_01ARZ3NDEKTSV4RRFFQ69G5KYC/upload \
  -H "X-Api-Key: $API_KEY" \
  -H "X-Timestamp: $TIMESTAMP" \
  -H "X-Nonce: $(uuidgen)" \
  -H "X-Signature: $SIGNATURE" \
  -F "file=@jane_payslips.pdf" \
  -F "file_type=SOURCE_OF_FUNDS"

Notes:

  • Repeat the upload with file_type=PROOF_OF_ADDRESS (for example a utility bill or bank statement).
  • SOURCE_OF_FUNDS is accepted for individuals only; sending it for a business returns 400 VALIDATION_ERROR.
  • A missing document comes back from step 4 as 422 MISSING_KYC_FIELDS with files.SOURCE_OF_FUNDS or files.PROOF_OF_ADDRESS in details.missing.
  • A proof of address already accepted during onboarding is reused, so a second request does not discard evidence that has already cleared review.
  • Accepted formats are PDF, JPG, JPEG, and PNG, up to 10 MB each.


4. Submit the request and track the review

Submit the request

POST /v1/payments/customers/{customer_id}/limit-requests

curl -X POST https://api-staging.checker.finance/v1/payments/customers/cus_01ARZ3NDEKTSV4RRFFQ69G5KYC/limit-requests \
  -H "X-Api-Key: $API_KEY" \
  -H "X-Timestamp: $TIMESTAMP" \
  -H "X-Nonce: $(uuidgen)" \
  -H "X-Signature: $SIGNATURE" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "provider-a"
  }'

Response — 202 Accepted:

{
  "provider": "provider-a",
  "status": "REQUESTED",
  "requested_at": "2026-10-21T14:05:00Z"
}

To skip step 2 and send the profile with the request, add it as profile:

{
  "provider": "provider-a",
  "profile": {
    "occupation": "SOFTWARE_DEVELOPER",
    "employment_status": "EMPLOYED",
    "source_of_funds": ["EMPLOYMENT_INCOME", "PERSONAL_SAVINGS"],
    "purpose_of_account": ["SALARY_AND_INCOME_RECEIPT", "PERSONAL_EXPENSES"],
    "anticipated_monthly_activity": "UNDER_100K"
  }
}

The profile is stored on the customer before the request is submitted, so the two routes end in the same state. Omit profile to use whatever is already on the customer.

Notes:

  • Submitting again while a request is still REQUESTED returns 200 OK with that open request and starts no second review.
  • A customer not yet ACTIVE at the corridor returns 400 CUSTOMER_INACTIVE. Poll GET /v1/payments/customers/{customer_id} and retry once the corridor reports ACTIVE.
  • A BUSINESS customer returns 400 VALIDATION_ERROR; a corridor that does not review limits returns 422 OPERATION_NOT_SUPPORTED.
  • An incomplete profile or a missing document returns 422 MISSING_KYC_FIELDS with details.missing naming every gap at once, e.g. ["kyc.risk_profile.occupation", "files.SOURCE_OF_FUNDS"]. Fill them and retry.

Track the review

GET /v1/payments/customers/{customer_id}/limit-requests

curl https://api-staging.checker.finance/v1/payments/customers/cus_01ARZ3NDEKTSV4RRFFQ69G5KYC/limit-requests \
  -H "X-Api-Key: $API_KEY" \
  -H "X-Timestamp: $TIMESTAMP" \
  -H "X-Nonce: $(uuidgen)" \
  -H "X-Signature: $SIGNATURE"

Response — 200 OK:

{
  "data": [
    {
      "provider": "provider-a",
      "status": "REVIEWED",
      "requested_at": "2026-10-21T14:05:00Z",
      "reviewed_at": "2026-10-21T15:30:00Z",
      "limits": [
        {
          "period": "DAILY",
          "currency": "USD",
          "amount": "25000.00"
        },
        {
          "period": "ROLLING_30D",
          "currency": "USD",
          "amount": "100000.00"
        }
      ]
    }
  ]
}

Poll until status becomes REVIEWED. The list holds the latest request per corridor, newest first, and returns an empty data array when none has been made.

StatusMeaning
REQUESTEDThe review is still open. No reviewed_at and no limits yet.
REVIEWEDThe corridor has finished reviewing. limits holds the ceilings in effect afterwards.

REVIEWED does not mean "approved". The corridor reports the limits in effect after its review. A review can leave the limits exactly as they were.

limits is the snapshot taken at review time and does not change afterwards. For live headroom, go back to step 1 — GET /v1/payments/customers/{customer_id}/limits reports the current ceilings with used and remaining tracking payouts against them.



Did this page help you?