# Step 1: request presigned upload URLs
curl --request POST \
--url https://api.sandbox.goteal.co/entries/payslips/presign \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"files": [
{"file_name": "payslip1.pdf", "external_id": "ext-jan-2024"},
{"file_name": "payslip2.pdf"}
]
}'
# Step 2: upload PDFs with the provided presigned URLs
curl --request PUT \
--url "<presigned_url_from_step_1>" \
--header 'Content-Type: application/octet-stream' \
--data-binary '@./fixtures/payslip1.pdf'
# Step 3: submit uploaded payslips for processing
curl --request POST \
--url https://api.sandbox.goteal.co/entries/payslips \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"files": [
{"path": "client/acct123/users/user456/payslip1.pdf", "external_document_id": "ext-jan-2024"},
{"path": "client/acct123/users/user456/payslip2.pdf"}
]
}'
{
"account_id": "95a0e70b-fe02-4f47-aef9-2efff279df71",
"entry_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"payroll_submissions": [
{
"id": "95a0e70b-fe02-4f47-aef9-2efff279df71",
"account_id": "674744df-9626-47ef-ae2b-4a491be136b5",
"entry_id": "be770ba4-1362-46cd-8c1c-2330ce3a8b69",
"created_at": "2019-05-17T00:00:00.000Z",
"document_external_id": "payslip123456",
"document_filename": "file1-payslip.pdf",
"identity_information": {
"name": "John Smith",
"date_of_birth": "2019-05-17T00:00:00.000Z",
"address": {
"street": "123 Main Street",
"county": "Greater London",
"city": "London",
"post_code": "SW1A 1AA",
"country": "United Kingdom"
},
"email": "[email protected]",
"phone": 447123456789,
"NI_number": "AB123456C"
},
"employment_information": {
"employer_name": "Acme Ltd",
"role": "Software Engineer",
"type": "Full-time",
"status": "Active",
"start_date": "2019-05-17T00:00:00.000Z",
"leave_date": "2019-05-17T00:00:00.000Z"
},
"income_information": {
"pay_date": "2023-05-27T00:00:00.000Z",
"pay_interval_start": "2023-05-01T00:00:00.000Z",
"pay_interval_end": "2023-05-31T00:00:00.000Z",
"pay_frequency": "Monthly",
"earnings": {
"gross_pay": 3500,
"net_pay": 2500,
"base_salary": 3000,
"bonus": 500
},
"deductions": {
"income_tax": 500,
"employee_ni": 200,
"employee_pension": 300,
"total_deductions": 1000
}
}
},
"fraud_risk": "Low"
],
"payslip_errors" : [{
"error" : "File is not a payslip",
"file_name" : "Payslip3.pdf"
}]
}
Uploading payslips is a three-step flow:
POST /entries/payslips/presign, providing
each PDF file name (and optional external identifier). The response
includes presigned_url and path values for every requested file.presigned_url using an HTTP PUT
request with Content-Type: application/octet-stream. Each file must be a
searchable, machine-readable PDF (scanned images are not supported).path (and optional external_document_id) for every
uploaded file so Teal can process the documents.
The path values you submit must match the ones returned by the presign
step. Any files that failed validation or upload are reported in the
payslip_errors array.# Step 1: request presigned upload URLs
curl --request POST \
--url https://api.sandbox.goteal.co/entries/payslips/presign \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"files": [
{"file_name": "payslip1.pdf", "external_id": "ext-jan-2024"},
{"file_name": "payslip2.pdf"}
]
}'
# Step 2: upload PDFs with the provided presigned URLs
curl --request PUT \
--url "<presigned_url_from_step_1>" \
--header 'Content-Type: application/octet-stream' \
--data-binary '@./fixtures/payslip1.pdf'
# Step 3: submit uploaded payslips for processing
curl --request POST \
--url https://api.sandbox.goteal.co/entries/payslips \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"files": [
{"path": "client/acct123/users/user456/payslip1.pdf", "external_document_id": "ext-jan-2024"},
{"path": "client/acct123/users/user456/payslip2.pdf"}
]
}'
{
"account_id": "95a0e70b-fe02-4f47-aef9-2efff279df71",
"entry_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"payroll_submissions": [
{
"id": "95a0e70b-fe02-4f47-aef9-2efff279df71",
"account_id": "674744df-9626-47ef-ae2b-4a491be136b5",
"entry_id": "be770ba4-1362-46cd-8c1c-2330ce3a8b69",
"created_at": "2019-05-17T00:00:00.000Z",
"document_external_id": "payslip123456",
"document_filename": "file1-payslip.pdf",
"identity_information": {
"name": "John Smith",
"date_of_birth": "2019-05-17T00:00:00.000Z",
"address": {
"street": "123 Main Street",
"county": "Greater London",
"city": "London",
"post_code": "SW1A 1AA",
"country": "United Kingdom"
},
"email": "[email protected]",
"phone": 447123456789,
"NI_number": "AB123456C"
},
"employment_information": {
"employer_name": "Acme Ltd",
"role": "Software Engineer",
"type": "Full-time",
"status": "Active",
"start_date": "2019-05-17T00:00:00.000Z",
"leave_date": "2019-05-17T00:00:00.000Z"
},
"income_information": {
"pay_date": "2023-05-27T00:00:00.000Z",
"pay_interval_start": "2023-05-01T00:00:00.000Z",
"pay_interval_end": "2023-05-31T00:00:00.000Z",
"pay_frequency": "Monthly",
"earnings": {
"gross_pay": 3500,
"net_pay": 2500,
"base_salary": 3000,
"bonus": 500
},
"deductions": {
"income_tax": 500,
"employee_ni": 200,
"employee_pension": 300,
"total_deductions": 1000
}
}
},
"fraud_risk": "Low"
],
"payslip_errors" : [{
"error" : "File is not a payslip",
"file_name" : "Payslip3.pdf"
}]
}
POST /entries/payslips/presign with the list
of filenames (and optional external identifiers) you intend to upload. The
response returns presigned_url and path fields for each file.presigned_url, perform an HTTP PUT
with Content-Type: application/octet-stream, streaming the PDF bytes. Files must be
searchable, machine-readable PDFs (scanned images are not supported).POST /entries/payslips (this endpoint) with a
JSON payload that includes the path for each uploaded file and an optional
external_document_id. Teal uses this metadata to process the uploaded
documents. Any files that fail validation are listed in payslip_errors in
the response.# Step 1: request presigned upload URLs
curl --request POST \
--url https://api.sandbox.goteal.co/entries/payslips/presign \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"files": [
{"file_name": "payslip1.pdf", "external_id": "ext-jan-2024"},
{"file_name": "payslip2.pdf"}
]
}'
# Step 2: upload PDFs with the provided presigned URLs
curl --request PUT \
--url "<presigned_url_from_step_1>" \
--header 'Content-Type: application/octet-stream' \
--data-binary '@./fixtures/payslip1.pdf'
# Step 3: submit uploaded payslips for processing
curl --request POST \
--url https://api.sandbox.goteal.co/entries/payslips \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"files": [
{"path": "client/acct123/users/user456/payslip1.pdf", "external_document_id": "ext-jan-2024"},
{"path": "client/acct123/users/user456/payslip2.pdf"}
]
}'
{
"account_id": "95a0e70b-fe02-4f47-aef9-2efff279df71",
"entry_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"payroll_submissions": [
{
"id": "95a0e70b-fe02-4f47-aef9-2efff279df71",
"account_id": "674744df-9626-47ef-ae2b-4a491be136b5",
"entry_id": "be770ba4-1362-46cd-8c1c-2330ce3a8b69",
"created_at": "2019-05-17T00:00:00.000Z",
"document_external_id": "payslip123456",
"document_filename": "file1-payslip.pdf",
"identity_information": {
"name": "John Smith",
"date_of_birth": "2019-05-17T00:00:00.000Z",
"address": {
"street": "123 Main Street",
"county": "Greater London",
"city": "London",
"post_code": "SW1A 1AA",
"country": "United Kingdom"
},
"email": "[email protected]",
"phone": 447123456789,
"NI_number": "AB123456C"
},
"employment_information": {
"employer_name": "Acme Ltd",
"role": "Software Engineer",
"type": "Full-time",
"status": "Active",
"start_date": "2019-05-17T00:00:00.000Z",
"leave_date": "2019-05-17T00:00:00.000Z"
},
"income_information": {
"pay_date": "2023-05-27T00:00:00.000Z",
"pay_interval_start": "2023-05-01T00:00:00.000Z",
"pay_interval_end": "2023-05-31T00:00:00.000Z",
"pay_frequency": "Monthly",
"earnings": {
"gross_pay": 3500,
"net_pay": 2500,
"base_salary": 3000,
"bonus": 500
},
"deductions": {
"income_tax": 500,
"employee_ni": 200,
"employee_pension": 300,
"total_deductions": 1000
}
}
},
"fraud_risk": "Low"
],
"payslip_errors" : [{
"error" : "File is not a payslip",
"file_name" : "Payslip3.pdf"
}]
}
Bearer token for authentication. The token should be the one returned by the /user-tokens endpoint.
Created
The id of the account
"95a0e70b-fe02-4f47-aef9-2efff279df71"
The id of the entry
Show child attributes
"95a0e70b-fe02-4f47-aef9-2efff279df71"
The id of the account
"674744df-9626-47ef-ae2b-4a491be136b5"
The id of the entry
"be770ba4-1362-46cd-8c1c-2330ce3a8b69"
The date the payroll was submitted
"2019-05-17T00:00:00.000Z"
Show child attributes
The full name of the user
"John Smith"
"2019-05-17T00:00:00.000Z"
Show child attributes
The street of the address
"123 Main Street"
The county of the address
"Greater London"
The city of the address
"London"
The post code of the address
"SW1A 1AA"
The country of the address
"United Kingdom"
The email of the user
The phone number of the user
447123456789
The national insurance number of the user
"AB123456C"
Show child attributes
The name of the employer
"Acme Ltd"
The role of the user
"Software Engineer"
The type of employment
"Full-time"
The status of the employment. Status active will be used when the user is employed in the company, alternatively inactive will be used when the user is not employed in the company anymore.
active, inactive "active"
"2019-05-17T00:00:00.000Z"
"2019-05-17T00:00:00.000Z"
Show child attributes
The date the payroll was submitted
"2023-05-27T00:00:00.000Z"
The start date of the pay interval
"2023-05-01T00:00:00.000Z"
The end date of the pay interval
"2023-05-31T00:00:00.000Z"
The frequency of the pay
"Monthly"
Show child attributes
The gross pay
3500
The net pay
2500
The base salary
3000
The bonus
500
Show child attributes
The income tax
500
The employee national insurance
200
The employee pension
300
The total deductions
1000
The id of the document
"95a0e70b-fe02-4f47-aef9-2efff279df71"
A string coming from the parameters of the uploaded payslip1.pdf either the form field name or external_document_id header for the file part. It might not be unique and depends on what's passed when uploading. If the payroll submission doesn't originate from a payslip this will be null.
"payslip123456"
If the payroll submission originates from a payslip this will be the file name of the uploaded payslip. It will be duplicate if same file names are uploaded If the payroll submission doesn't originate from a payslip this will be null.
"file1-payslip.pdf"
The fraud risk level assessment. Fraud risk will be present if the payroll data is coming from a payslip source
Low, Medium, High "Low"