สแกนผ่าน API
การสแกนผ่าน API เปลี่ยนไฟล์ PDF ให้เป็นสำเนาที่สแกนอย่างสมจริงด้วยการเรียก REST เพียงครั้งเดียว เหมาะกับงานอัตโนมัติและการเชื่อมต่อกับแอป สร้างงาน อัปโหลด PDF แล้วสอบถามสถานะหรือรอ webhook เพียงสามขั้นตอน จากสภาพแวดล้อมหรือภาษาใดก็ได้ที่ส่งคำขอ HTTP เป็น ปริภูมิสี ความละเอียด การหมุน ความเบลอ นอยส์ ความสว่าง คอนทราสต์ และขอบ ตั้งค่าได้ทั้งหมด
ขั้นตอนการเรียกใช้
สร้างงาน
POST /v1/scan-jobs
ส่ง config ของคุณพร้อม webhookUrl ถ้าต้องการ แล้วจะได้ jobID และ uploadURL ที่ลงลายเซ็นล่วงหน้ากลับมา
อัปโหลด PDF
PUT {uploadURL}
ส่งไฟล์ด้วย PUT ตรงไปยังที่อยู่ S3 ที่ลงลายเซ็นล่วงหน้าจากขั้นก่อนหน้า ไม่ต้องแนบโทเค็น
รับสำเนาที่สแกน
GET /v1/scan-jobs/{jobID}
สอบถามสถานะหรือรอ webhook เมื่องานเป็น completed แล้วจึงดาวน์โหลดจาก downloadURL
เหมาะกับงานแบบไหน
ออกเอกสารเป็นชุดจากฝั่งเซิร์ฟเวอร์
สัญญา ใบแจ้งหนี้ และรายงานที่สร้างบนเซิร์ฟเวอร์ผ่านเอฟเฟกต์สแกนได้ทันที ไม่ต้องมีใครมาทำซ้ำด้วยมือบนหน้าเว็บ
ต่อเข้ากับระบบเดิม
เพิ่มคำสั่ง «ส่งออกสำเนาที่สแกน» ลงใน CRM, ERP หรือระบบใบงาน แล้วให้มันเรียก API
สายงานอัตโนมัติ
CI หรือ n8n, Zapier และแพลตฟอร์มทำนองนี้เริ่มงานตามเหตุการณ์ แล้วให้ webhook ส่งต่อไปขั้นถัดไปเมื่อเสร็จ
คิวไฟล์จำนวนมาก
งานทำงานแบบอะซิงโครนัส เมื่อสร้างแล้วแต่ละงานจะถูกประมวลผลแยกกัน และดูความคืบหน้าได้ผ่าน status กับ createdAfter
ภาษาและสภาพแวดล้อมที่รองรับ
API เป็น HTTP และ JSON มาตรฐาน ภาษาหรือแพลตฟอร์มอัตโนมัติใดที่ส่งคำขอได้ก็เรียกใช้ได้
ตัวอย่างโค้ด
Add Look Scanned API Scan to this project, so I can turn a PDF into a
realistic scanned copy from code.
API docs: https://lookscanned.io/en/scan/api
Write one function that:
1. POST https://api.lookscanned.io/v1/scan-jobs
Header: Authorization: Bearer $LOOKSCANNED_API_TOKEN
Body: {"config": {"colorspace": "gray", "resolution": 150, "rotate": 1}}
It returns jobID and a presigned uploadURL.
2. PUT the PDF bytes to uploadURL with Content-Type: application/pdf.
Send no Authorization header — that URL is already signed.
3. Poll GET /v1/scan-jobs/{jobID} until status is "completed" (or "failed"),
then return downloadURL.
Read the token from the LOOKSCANNED_API_TOKEN environment variable. Use the
language and HTTP client this project already uses, and add one test.interface ScanConfig {
rotate?: number // degrees to rotate the document
rotate_var?: number // degrees to rotate the document randomly
colorspace?: 'gray' | 'sRGB' // the colorspace of the output image
blur?: number // the amount of blur to apply to the image
noise?: number // the amount of noise to apply to the image
border?: boolean // whether to add a border to the image
brightness?: number // the brightness of the image. 1 is no change
contrast?: number // the contrast of the image. 1 is no change
resolution?: number // the resolution of the image in DPI
output_format?: 'image/png' | 'image/jpeg' // the format of the output image
}
interface ScanOptions {
config: ScanConfig
webhookUrl?: string // webhook URL to notify when job is completed
}
interface ScanResponse {
jobID: string // UUID of the scan job
userID: string // UUID of the user who created the job
createdAt: number // timestamp of job creation
status: 'pending' | 'processing' | 'completed' | 'failed'
config: ScanConfig
inputUploadedAt?: number // timestamp when input file was uploaded
completedAt?: number // timestamp when job was completed
webhookUrl?: string // webhook URL for notifications
uploadURL?: string // S3 presigned URL for file upload
downloadURL?: string // S3 presigned URL for file download
}
async function apiScan(pdfBlob: Blob, scanOptions: ScanOptions, token: string): Promise<ScanResponse> {
const response = await fetch('https://api.lookscanned.io/v1/scan-jobs', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`
},
body: JSON.stringify(scanOptions)
})
const result: ScanResponse = await response.json()
// PUT PDF Blob to upload URL
const uploadURL = result.uploadURL
await fetch(uploadURL, {
method: 'PUT',
headers: {
'Content-Type': 'application/pdf',
'Content-Length': pdfBlob.size.toString()
},
body: pdfBlob
})
// get scan job status
const jobStatusResponse = await fetch(`https://api.lookscanned.io/v1/scan-jobs/${result.jobID}`, {
headers: {
'Authorization': `Bearer ${token}`
}
})
return await jobStatusResponse.json()
}import requests
def api_scan(pdf_file, scan_options, token):
# Create scan job
response = requests.post(
'https://api.lookscanned.io/v1/scan-jobs',
headers={'Authorization': f'Bearer {token}'},
json=scan_options
)
result = response.json()
# Upload PDF to presigned URL
upload_url = result['uploadURL']
requests.put(
upload_url,
headers={
'Content-Type': 'application/pdf',
'Content-Length': str(len(pdf_file))
},
data=pdf_file
)
# Get scan job status
job_status = requests.get(
f'https://api.lookscanned.io/v1/scan-jobs/{result["jobID"]}',
headers={'Authorization': f'Bearer {token}'}
)
return job_status.json()
# Example usage
if __name__ == "__main__":
with open('document.pdf', 'rb') as f:
pdf_content = f.read()
options = {
'config': {
# Optional parameters:
# 'rotate': 0, # degrees to rotate the document
# 'colorspace': 'gray', # gray or sRGB
# 'resolution': 300, # DPI
# 'rotate_var': 0, # random rotation variance in degrees
# 'blur': 0, # amount of blur
# 'noise': 0, # amount of noise
# 'border': False, # whether to add border
# 'brightness': 1, # 1 is no change
# 'contrast': 1, # 1 is no change
# 'output_format': 'image/png' # image/png or image/jpeg
},
'webhookUrl': 'https://example.com/webhook'
}
result = api_scan(pdf_content, options, 'your-api-token')
print(f"Scan job created with ID: {result['jobID']}")# Set your API token and PDF file as environment variables
export LOOKSCANNED_API_TOKEN='your_api_token_here'
# Create a new scan job
curl -X POST 'https://api.lookscanned.io/v1/scan-jobs' \
-H "Authorization: Bearer ${LOOKSCANNED_API_TOKEN}" \
-H 'Content-Type: application/json' \
-d '{
"config": {
"rotate": 0,
"rotate_var": 1,
"colorspace": "gray",
"blur": 0.2,
"noise": 0.1,
"border": true,
"brightness": 1.0,
"contrast": 1.0,
"resolution": 300,
"output_format": "image/jpeg"
},
"webhookUrl": "https://your-domain.com/webhook"
}'
# Response will include uploadURL and jobID
# {
# "jobID": "550e8400-e29b-41d4-a716-446655440000",
# "userID": "446655440000-e29b-41d4-a716-550e8400",
# "createdAt": 1616161616,
# "status": "created",
# "uploadURL": "...",
# "config": { ... }
# }
# Upload PDF file to the presigned URL
curl -X PUT 'PRESIGNED_UPLOAD_URL' \
-H 'Content-Type: application/pdf' \
-H "Content-Length: PDF_FILE_SIZE" \
--data-binary "@path/to/your/file.pdf"
# Check job status
curl 'https://api.lookscanned.io/v1/scan-jobs/JOB_ID' \
-H "Authorization: Bearer ${LOOKSCANNED_API_TOKEN}"
# Response will include status and downloadURL when completed
# {
# "jobID": "550e8400-e29b-41d4-a716-446655440000",
# "status": "completed",
# "downloadURL": "...",
# ...
# }
# Download the PDF
curl -o scanned.pdf 'DOWNLOAD_URL'API Bearer Token
โทเค็นผูกกับบัญชีของคุณและสร้างใหม่ได้ทุกเมื่อ การสแกนผ่าน API ต้องใช้บัญชี Pro ถ้าไม่มีโทเค็นที่ใช้ได้ API จะตอบ 401 และถ้าไม่มีบทบาท Pro จะตอบ 403
การสแกนผ่าน API เป็นฟีเจอร์ของ Pro
บัญชีนี้ยังไม่ได้เป็น Pro อัปเกรดแล้วโทเค็นจะแสดงตรงนี้ หากไม่มีโทเค็นหรือไม่มีบทบาท API จะตอบ 401 / 403
ลองใช้ดู
ปรับพารามิเตอร์แล้วดูเนื้อหาคำขอเปลี่ยนตาม จากนั้นเรียก API ทั้งสามขั้นตามลำดับ
พารามิเตอร์การสแกน
การทดลองเรียกใช้โทเค็นของคุณเรียก API จึงต้องมีบัญชี Pro ส่วนพารามิเตอร์และเนื้อหาคำขอดูได้ตามสบาย
{
"config": {
"rotate": 1,
"rotate_var": 0.5,
"colorspace": "gray",
"blur": 0,
"noise": 0,
"border": false,
"brightness": 1.3,
"contrast": 1.3,
"resolution": 150,
"output_format": "image/jpeg"
}
}ข้อมูลงานสแกน
ตัวอย่าง{
"jobID": "3f9c1e64-0000-4000-8000-00000000a71b",
"userID": "8f21c4b0-0000-4000-8000-000000004a17",
"createdAt": 1724409600,
"status": "completed",
"inputUploadedAt": 1724409601,
"completedAt": 1724409602,
"numPages": 6,
"downloadURL": "https://…/output/3f9c.pdf?X-Amz-…"
}คู่มืออ้างอิง API
| เมท็อด | เส้นทาง | คำอธิบาย |
|---|---|---|
| POST | /v1/scan-jobs | สร้างงานสแกน ส่ง config และ webhookUrl ถ้าจำเป็น แล้วจะได้ออบเจ็กต์ของงานที่มีสถานะ created พร้อม uploadURL ที่ลงลายเซ็นล่วงหน้ากลับมา |
| PUT | {uploadURL}ที่อยู่ S3 ที่ลงลายเซ็นล่วงหน้าจากขั้นก่อนหน้า ซึ่งไม่ได้อยู่บน api.lookscanned.io | อัปโหลด PDF ต้นฉบับพร้อม Content-Type: application/pdf และ Content-Length ที่อยู่มีลายเซ็นในตัวอยู่แล้ว จึงไม่ต้องใส่ส่วนหัว Authorization |
| GET | /v1/scan-jobs/{jobID} | อ่านงานเดียว ใช้สำหรับสอบถามสถานะ เมื่อเป็น created จะมี uploadURL และเมื่อเป็น completed จะมี downloadURL |
| GET | /v1/scan-jobs | แสดงรายการงานของคุณเอง กรองตาม jobID, status หรือ createdAfter ได้ |
401ไม่มีโทเค็นที่ใช้ได้403บัญชีไม่ใช่ Pro404ไม่พบงานนี้
เนื้อหาคำขอ
| ฟิลด์ | ชนิด | ค่าเริ่มต้น | คำอธิบาย |
|---|---|---|---|
| webhookUrl | string · — | — | ถูกเรียกหนึ่งครั้งเมื่องานเสร็จ จึงไม่ต้องคอยสอบถามสถานะเอง |
| config.colorspace | 'gray' | 'sRGB' · gray | gray | ปริภูมิสีของภาพผลลัพธ์ โดย gray คือสำเนาที่สแกนแบบขาวดำ |
| config.resolution | number · 72 | 72 | ความละเอียดของภาพผลลัพธ์ หน่วยเป็น DPI |
| config.rotate | number · — | — | การหมุนของทั้งเอกสาร หน่วยเป็นองศา |
| config.rotate_var | number · — | — | ช่วงการหมุนแบบสุ่มของแต่ละหน้า หน่วยเป็นองศา ให้ดูเหมือนวางกระดาษเอียง |
| config.blur | number · 0 | 0 | ระดับความเบลอ |
| config.noise | number · 0 | 0 | ระดับนอยส์ |
| config.brightness | number · 1 | 1 | ความสว่าง โดย 1 คือไม่เปลี่ยน |
| config.contrast | number · 1 | 1 | คอนทราสต์ โดย 1 คือไม่เปลี่ยน |
| config.border | boolean · false | false | จะใส่ขอบของการสแกนให้หน้ากระดาษหรือไม่ |
| config.output_format | 'image/png' | 'image/jpeg' · image/jpeg | image/jpeg | รูปแบบภาพที่ใช้ตอนเรนเดอร์หน้ากระดาษ |
ทุกฟิลด์ละไว้ได้ ค่าตั้งต้นในส่วน «ลองใช้ดู» ได้แก่ ความละเอียด 150 การหมุน 1 ความสว่างและคอนทราสต์ 1.3 เป็นชุดค่าที่เว็บแอปแนะนำ ไม่ใช่ค่าเริ่มต้นของ API
ฟิลด์ที่ควรสังเกตในออบเจ็กต์ของงาน
- status
- created / processing / completed / failed เป็นตัวกำหนดว่าที่อยู่สองรายการด้านล่างจะปรากฏหรือไม่
- uploadURL
- มีเฉพาะตอนเป็น created เป็นที่อยู่สำหรับอัปโหลดที่ลงลายเซ็นล่วงหน้าและมีอายุจำกัด
- downloadURL
- มีเฉพาะเมื่อเป็น completed เป็นที่อยู่สำหรับดาวน์โหลดที่ลงลายเซ็นล่วงหน้าและมีอายุจำกัด
- inputUploadedAt / completedAt
- เวลาที่อัปโหลดต้นฉบับเสร็จและเวลาที่งานเสร็จ ผลต่างคือเวลาที่ใช้ประมวลผล
คำถามที่พบบ่อย
การสแกนผ่าน API ต้องใช้ Pro ไหม
ต้องใช้ ถ้าไม่มีโทเค็นที่ใช้ได้ API จะตอบ 401 และบัญชีที่ไม่มีบทบาท Pro จะได้ 403 เมื่ออัปเกรดและเข้าสู่ระบบแล้ว จะรับโทเค็นได้จากหน้านี้
จะรู้ได้อย่างไรว่างานเสร็จเมื่อไหร่
มีสองวิธี คือสอบถาม GET /v1/scan-jobs/{jobID} เป็นระยะ หรือส่ง webhookUrl ตอนสร้างงานแล้วให้บริการเรียกกลับหนึ่งครั้งเมื่อเสร็จ
ผลลัพธ์เหมือนกับการสแกนบนหน้าเว็บไหม
เหมือนกัน ทั้งสองทางใช้การทำงานของเอฟเฟกต์สแกนชุดเดียวกัน และปริภูมิสี ความละเอียด การหมุน ความเบลอ นอยส์ ความสว่าง คอนทราสต์ และขอบใน config ตรงกับตัวเลือกชื่อเดียวกันบนหน้าเว็บ ค่าพารามิเตอร์เดียวกันย่อมได้ผลลัพธ์เดียวกัน ต่างกันแค่ที่ประมวลผล คือหน้าเว็บทำในเครื่อง ส่วน API ทำที่บริการระยะไกล
เก็บที่อยู่สำหรับอัปโหลดและดาวน์โหลดไว้ใช้ซ้ำได้ไหม
ไม่แนะนำ uploadURL และ downloadURL เป็นที่อยู่ที่ลงลายเซ็นล่วงหน้าและมีอายุจำกัด เมื่อหมดอายุต้องอ่านข้อมูลงานอีกครั้งเพื่อรับที่อยู่ใหม่
งานหนึ่งใช้เวลานานเท่าไร
ขึ้นกับจำนวนหน้าและความละเอียด เอกสารไม่กี่หน้ามักเสร็จภายในไม่กี่วินาที ยิ่งความละเอียดสูงและหน้ามากก็ยิ่งใช้เวลานาน ใช้ผลต่างของ inputUploadedAt กับ completedAt คำนวณเวลาจริงได้
ถ้างานล้มเหลวต้องทำอย่างไร
สถานะจะกลายเป็น failed สาเหตุที่พบบ่อยคือไฟล์ไม่ใช่ PDF ที่ถูกต้อง ถูกจำกัดด้วยการเข้ารหัส หรือการอัปโหลดถูกขัดจังหวะ ตรวจว่าไฟล์เปิดได้แล้วสร้างงานใหม่อีกครั้ง
ดูงานย้อนหลังได้ไหม
ได้ GET /v1/scan-jobs จะแสดงรายการงานของคุณเอง และกรองตาม jobID, status, createdAfter ได้ เพียงพอสำหรับการกระทบยอดหรือดาวน์โหลดซ้ำ