API স্ক্যান
API স্ক্যান একটি REST কলের মাধ্যমে PDF-কে বিশ্বাসযোগ্য স্ক্যান করা নথিতে বদলে দেয়, যা স্বয়ংক্রিয় প্রক্রিয়া ও অ্যাপ সংযুক্তির জন্য উপযোগী। জব তৈরি করুন, PDF আপলোড করুন, তারপর অবস্থা জানতে চান বা webhook-এর অপেক্ষা করুন — তিনটি ধাপ, HTTP অনুরোধ পাঠাতে পারে এমন যেকোনো পরিবেশ বা ভাষা থেকে। রঙের পরিসর, রেজোলিউশন, ঘূর্ণন, ঝাপসা ভাব, নয়েজ, উজ্জ্বলতা, কনট্রাস্ট ও বর্ডার সবই আপনার হাতে।
একটি কল কীভাবে চলে
জব তৈরি করুন
POST /v1/scan-jobs
আপনার config আর চাইলে একটি webhookUrl পাঠান; বিনিময়ে jobID এবং প্রাক-স্বাক্ষরিত uploadURL পাবেন।
PDF আপলোড করুন
PUT {uploadURL}
ফাইলটি সরাসরি আগের ধাপের প্রাক-স্বাক্ষরিত S3 ঠিকানায় PUT করুন — টোকেন লাগবে না।
স্ক্যান করা নথি নিন
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অ্যাকাউন্ট Pro নয়404এমন কোনো জব নেই
অনুরোধের বডি
| ফিল্ড | ধরন | ডিফল্ট | বিবরণ |
|---|---|---|---|
| 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 দিয়ে ছেঁকে নেওয়া যায়, যা মিলিয়ে দেখা বা আবার নামানোর জন্য যথেষ্ট।