Upload Documents and Proofs
Declare supporting documents for an entity and upload the files (proofs) that Localpayment reviews during KYC/KYB.
A document is the declared data (type and number). A proof is a file that supports it. This guide shows how to add documents to an entity, upload their files one by one, replace or remove files, and check that every document is covered so the entity is ready for review.
Prerequisites
- An entity created with Create an Entity, and the
documentIdof each of its documents. - Files in JPG, PNG, or PDF, up to 10 MB each.
Files per document
A document holds as many files as you need. Each file has a type:
| proofType | Typical use | Behavior on a new upload |
|---|---|---|
| FRONT | Front side of an identity document, or the single image of a document. | Replaces the current file, which becomes SUPERSEDED. |
| BACK | Back side of an identity document. | Replaces the current file, which becomes SUPERSEDED. |
| SELFIE | Photo of the person, uploaded on the identity document itself. | Replaces the current file, which becomes SUPERSEDED. |
| DOCUMENT | Scanned document (PDF): proof of address, articles of incorporation, tax registration. | Adds a file, for example each page of a contract. |
| OTHER | Any other evidence. | Adds a file. |
An APPROVED file cannot be replaced (409 PROOF_APPROVED). A file uploaded by mistake can be removed with Delete a Proof while it is not approved.
%%{init: {'theme': 'base', 'themeVariables': {'background': '#ffffff', 'primaryColor': '#31467c', 'primaryTextColor': '#ffffff', 'primaryBorderColor': '#0c1a29', 'secondaryColor': '#31467c', 'tertiaryColor': '#ffffff', 'lineColor': '#0c1a29', 'textColor': '#0c1a29', 'edgeLabelBackground': '#ffffff', 'fontFamily': 'Manrope'}, 'fontFamily': 'Manrope', 'htmlLabels': false, 'flowchart': {'htmlLabels': false, 'wrappingWidth': 400, 'padding': 20}}}%%
flowchart TD
A["Your backend<br/>POST /api/entity/v1/entities/{entityId}/documents<br/>PROOF_OF_ADDRESS"] --> B["Entities API<br/>201: documentId"]:::lp
B --> C["Your backend<br/>POST /api/entity/v1/documents/{docId}/proofs?proofType=FRONT<br/>multipart file"]
C --> D["Entities API<br/>201: proof id, verificationStatus PENDING"]:::lp
D --> E["Your backend<br/>POST /api/entity/v1/documents/{docId}/proofs?proofType=DOCUMENT<br/>PDF"]
E --> F["Entities API<br/>201: proof id"]:::lp
F --> G["Your backend<br/>GET /api/entity/v1/entities/{entityId}/kyc-status"]
G --> H["Entities API<br/>200: documentationStatus COMPLETE"]:::lp
classDef default fill:#31467c,stroke:#0c1a29,stroke-width:1px,color:#ffffff,font-family:Manrope
classDef lp fill:#0c1a29,stroke:#0c1a29,color:#ffffff
classDef terminal fill:#0c1a29,stroke:#0c1a29,color:#ffffff
classDef lbl fill:#0c1a29,stroke:#0c1a29,color:#ffffff,font-size:13px
Step by step
- Declare the document if the entity does not have it yet, with Add a Document. Keep its
documentId. - Upload the file with Upload a Proof:
POST /api/entity/v1/documents/{docId}/proofs?proofType=FRONTasmultipart/form-data, with a part namedfile. - Check the upload: the 201 response must show
sizeBytesgreater than zero and the expectedmimeType. - Repeat for the back (
proofType=BACK) and the selfie (proofType=SELFIE) of the identity document, and for each other document. - Check coverage with Get KYC Status.
documentationStatusmust beCOMPLETEso the entity is ready for review.
Upload a file
curl -X POST "https://api.stage.localpayment.com/api/entity/v1/documents/2e16d844-4fa9-4295-9a21-83ec32ef241a/proofs?proofType=FRONT" \
-H "Authorization: Bearer $LOCALPAYMENT_ACCESS_TOKEN" \
-F "file=@id_front.jpg;type=image/jpeg"{
"id": "2c4c2f74-7179-4113-83fb-f11dbce9e07d",
"documentId": "2e16d844-4fa9-4295-9a21-83ec32ef241a",
"proofType": "FRONT",
"fileName": "id_front.jpg",
"mimeType": "image/jpeg",
"sizeBytes": 102400,
"verificationStatus": "PENDING",
"verifiedBy": null,
"verifiedAt": null,
"verificationReason": null,
"uploadedBy": "12345",
"uploadedAt": "2024-01-15T17:03:13Z",
"status": "CURRENT",
"supersededAt": null,
"supersededBy": null,
"replacedByProofId": null,
"deletedAt": null,
"deletedBy": null,
"inVerification": false
}In Python, check the size of the stored file and handle the upload errors:
import os
import requests
BASE_URL = "https://api.stage.localpayment.com/api/entity"
access_token = os.environ["LOCALPAYMENT_ACCESS_TOKEN"]
doc_id = "2e16d844-4fa9-4295-9a21-83ec32ef241a"
with open("id_front.jpg", "rb") as f:
response = requests.post(
f"{BASE_URL}/v1/documents/{doc_id}/proofs",
params={"proofType": "FRONT"},
files={"file": ("id_front.jpg", f, "image/jpeg")},
headers={"Authorization": f"Bearer {access_token}"},
timeout=60,
)
if response.status_code == 201:
proof = response.json()
if proof["sizeBytes"] == 0:
raise RuntimeError("Empty file stored: upload again with the same proofType")
elif response.status_code in (413, 415):
raise RuntimeError("Use a JPG, PNG, or PDF file of 10 MB or less")
elif response.status_code == 502:
pass # STORAGE_WRITE_FAILED: retry the upload
else:
problem = response.json()
# 409 PROOF_APPROVED or ENTITY_IN_REVIEW: the file cannot be replaced now
raise RuntimeError(f"{problem.get('code')} correlationId={problem.get('correlationId')}")Check coverage
KYC status once both files are in place:
{
"entityId": "5aced5da-40c1-4bec-85ff-c8cd1bcb4526",
"status": "PENDING_KYC",
"documentationStatus": "COMPLETE",
"statusReason": null,
"documents": [
{
"documentId": "2e16d844-4fa9-4295-9a21-83ec32ef241a",
"type": "CPF",
"status": "PENDING",
"proofs": [
{
"proofId": "2c4c2f74-7179-4113-83fb-f11dbce9e07d",
"verificationStatus": "PENDING"
}
]
},
{
"documentId": "e0ea9515-442e-4bc5-bc82-b8d278255c37",
"type": "PROOF_OF_ADDRESS",
"status": "PENDING",
"proofs": [
{
"proofId": "acb78b3f-fe18-4094-b6a9-2107f502d709",
"verificationStatus": "PENDING"
}
]
}
]
}Read files back
Get a Proof returns the metadata and a downloadUrl valid for 10 minutes. Download a Proof File redirects straight to it. Both are audited with the user in your access token.
The signed
downloadUrlgrants access to the file until it expires. Do not store it or share it with third parties. Request a new one when you need the file again.
Replace a rejected file
When Compliance rejects a proof, the document becomes REJECTED and verificationReason explains why:
{
"documentId": "0266257c-a2aa-49ac-99fe-b3882a51d750",
"entityId": "8f5b2c9a-1caf-4b2c-b085-82bbaead6ddd",
"type": "NATIONAL_ID",
"id": "00.000.000-0",
"issuingCountry": "BRA",
"issueDate": null,
"expirationDate": null,
"isPrimary": false,
"status": "REJECTED",
"metadata": null,
"proofs": [
{
"id": "931398af-9c77-4958-abf8-4c749147c508",
"documentId": "0266257c-a2aa-49ac-99fe-b3882a51d750",
"proofType": "BACK",
"fileName": "id_back.jpg",
"mimeType": "image/jpeg",
"sizeBytes": 98304,
"verificationStatus": "REJECTED",
"verifiedBy": "67890",
"verifiedAt": "2024-01-15T17:20:34Z",
"verificationReason": "Illegible image",
"uploadedBy": "12345",
"uploadedAt": "2024-01-15T17:19:49Z",
"status": "CURRENT",
"supersededAt": null,
"supersededBy": null,
"replacedByProofId": null,
"deletedAt": null,
"deletedBy": null,
"inVerification": false
}
],
"createdAt": "2024-01-15T17:19:46Z",
"updatedAt": "2024-01-15T17:19:46Z"
}Once the entity is back in PENDING_KYC, upload a new file with the same proofType. The rejected proof is replaced and the document returns to PENDING. When the corrections are done, call Request Verification again.
Edit a document
Update a Document changes the issuing country, the dates, and the metadata. Any change resets the document's approved proofs to PENDING. The type and number are immutable: add a new document and delete the old one instead. The primary document cannot be deleted.
Common errors
| Error | Cause | Fix |
|---|---|---|
| 413 FILE_TOO_LARGE | File larger than 10 MB. | Compress or split the file. |
| 415 UNSUPPORTED_FILE_TYPE | The file is not a JPG, PNG, or PDF. | Convert the file and upload it again. |
| 400 VALIDATION_ERROR | Missing or invalid proofType. | Check the query string. |
| 409 PROOF_APPROVED | The file you are replacing or deleting is already approved. | Keep it. Upload additional evidence as DOCUMENT or OTHER. |
| 409 ENTITY_IN_REVIEW | The entity is under review: no file can be uploaded, replaced, or deleted. | Wait for the outcome in Get KYC Status. |
| 409 ENTITY_NOT_EDITABLE | The entity is REJECTED, BLOCKED, or CLOSED. | Files cannot be added to that entity. |
| 201 with sizeBytes 0 | The multipart request had no file part. | Attach the file and upload again with the same proofType. |
Next steps
Updated 5 days ago
