Proof of income


Definition

During the onboarding process, each customer is assessed from an AML/CFT perspective.

If a customer is deemed to pose an increased risk, proof of income is requested as part of enhanced due diligence. This document is reviewed and validated by our KYC provider.





Sequence diagram

sequenceDiagram
Title: Proof of income
autoNumber
Participant User
Participant Partner
Participant XPO
Participant KYC provider


Note over User, XPO: Risk calculation
	XPO -->> XPO: risk calculation


Note over User, XPO: case risk high
rect rgb(251, 251,218)

XPO -->> Partner: webhook IncomeDemandChanged	 {status:Initialized}
Partner -->> User: proof of income expected
User -->> Partner: download proof of income
Partner ->> XPO : POST 3.0/users/{appUserId}/income/attachments
XPO -->> Partner: webhook IncomeDemandChanged	 {status:Pending}
XPO -->> KYC provider: send proof of income
KYC provider -->> XPO: proof validated
XPO -->> Partner: webhook IncomeDemandChanged	{status:Complete}

end



Status diagram

There are two statuses: the step status, and the status(es) of the income documentation.

Demand status: status

Status in the ressource income

stateDiagram

[*] --> Initialized: Open case on the provider's KYC side

Initialized -->Pending:proof of income expected
Pending --> Complete: proof of income validated
Pending --> Incomplete:proof of income refused
Incomplete --> Pending: new document submitted
Pending --> Rejected: document rejected and limit reached
Pending --> Expired:after 90 days
Pending --> FraudSuspicion

Complete --> [*]
Rejected  --> [*]
Expired  --> [*]
FraudSuspicion  --> [*]

Diligence statusreceivedDiligences.status

stateDiagram

[*] --> Received: proof of income received

Received --> Refused: proof of income refused
Received --> Validated:proof of income Validated

Refused --> [*]
Validated  --> [*]



Rules

Dependencies between the statuses of the document, the step, and the user

When the demand is rejected for IncomeReopening , the user can resubmit a new income document.

However, for other use cases, the step is refused. The relationState.status changes for AwaitingInactivation; the user is going to be closed.

CasereceivedDiligences.status(demand) statusrelationState
.status
relationState
.reasons
Proof of income refusedRejectedInProgressN/AIncomeReopening
3 attempts refusedRejectedRefusedAwaitingInactivationIncomeReopeningLimitReached
After 90 days without validationExpiredRefusedAwaitingInactivationIncomeTimedOut
Fraud suspicionFraudSuspicionRefusedAwaitingInactivationIncomeFraudConfirmed

Expected document

The required document is the tax assessment notice issued by the user's country of residence.

This document is controled automatically for France, manually for other countries.




Sequence diagram: red flow example

Here is the exemple for "3 attemps refused"

sequenceDiagram
Title: Proof of income refused
autoNumber
Participant User
Participant Partner
Participant XPO
Participant KYC provider


Note over User, XPO: Risk calculation
	XPO -->> XPO: risk calculation

Note over User, XPO: case risk high
rect rgb(255,235,232)

loop 3 times

  XPO -->> Partner: webhook IncomeDemandChanged	 {status:Initialized}
  Partner -->> User: proof of income expected
  User -->> Partner: download proof of income
	Partner ->> XPO : POST 3.0/users/{appUserId}/income/attachments
  XPO -->> Partner: webhook IncomeDemandChanged	 {status:Pending}
  XPO -->> KYC provider: send proof of income
  KYC provider -->> XPO: proof refused
  XPO -->> Partner: webhook IncomeDemandChanged	{status:Refused, receivedDiligences.status:Refused}

end

XPO -->> Partner: webhook UserCreatedOrUpdated	{relationState.status:Inactive, relationState.reasons:IncomeReopeningLimitReached}

end




How to test

You send a request via the usual upload endpoint, naming the attachment with
an “xp_” prefix followed by a keyword. The system intercepts the response and simulates the
corresponding status.


File nameResultExample
xp_accepted.pdfDiligence validatedxp_accepted.pdf
xp_.pdf
Diligence Refused, with reason code <reasonCode>
xp_document_front_missing.pdf
xxx.pdf (withou "xp_" prefix)Real behaviorincome.pdf
xp_unknown_keyword.pdfReal behaviorxp_income.pdf

Common reason codes:

  • DOCUMENT_FRONT_MISSING, DOCUMENT_BACK_MISSING
  • DOCUMENT_EXPIRED, DOCUMENT_TOO_OLD
  • DOCUMENT_UNREADABLE, DOCUMENT_QUALITY_INSUFFICIENT
  • NAME_MISMATCH, DOB_MISMATCH
  • IBAN_NAME_MISMATCH, TAX_NOTICE_VERIFICATION_FAILED
ExampleResult
xp_document_front_missing.pdfRefused — reason code DOCUMENT_FRONT_MISSING
xp_document_expired.pngRefused — reason code DOCUMENT_EXPIRED
xp_name_mismatch.jpgRefused — reason code NAME_MISMATCH



FAQ






Did this page help you?