Upload CV File Directly
Upload a CV file directly in a single request
This is the simplest upload method - send your CV file and metadata in one request, and get a fully processed document back.
How It Works
Single Request Upload:
- Send file as binary body + metadata in query parameters
- Document record created automatically
- CV analysis starts immediately
- Poll status endpoint for results
No presigned URLs needed - everything happens server-side.
Request Format
Query Parameters (Required)
| Parameter | Type | Required | Description | Example |
|---|---|---|---|---|
| documentName | string | Yes | Display name for CV | John Doe - Software Engineer |
| documentType | string | No | Document category (default: cv) | cv |
| documentDate | string | Yes | CV date in MM-YYYY format | 11-2025 |
Headers (Required)
| Header | Type | Required | Description | Example |
|---|---|---|---|---|
| X-API-Key | string | Yes | Your API key | YOUR_API_KEY |
| Content-Type | string | Yes | File MIME type | application/pdf |
Body
Send the raw file bytes as the request body (not form-data, not JSON).
Supported File Types
✅ PDF - application/pdf (recommended)
✅ DOCX - application/vnd.openxmlformats-officedocument.wordprocessingml.document
✅ DOC - application/msword
✅ TXT - text/plain
Maximum file size: 10 MB
Note: DOC and DOCX files are automatically converted to PDF during processing.
Response
Success (201 Created)
{
"documentId": "789e4567-e89b-12d3-a456-426614174000",
"status": "uploading",
"message": "Document uploaded and processing started",
"documentUrl": "s3://bucket/companies/.../documents/.../resume.pdf",
"file": {
"name": "john_doe_resume.pdf",
"size": 245760,
"sizeFormatted": "240 KB",
"contentType": "application/pdf"
},
"estimatedProcessingTime": "30 to 60 seconds",
"statusEndpoint": "/v1/public/documents/789e4567-e89b-12d3-a456-426614174000",
"nextSteps": [
"Poll GET /v1/public/documents/789e4567-... to check processing status",
"Document will be in 'completed' state when analysis is done"
]
}Processing Pipeline
After upload, your CV goes through this automated workflow:
- Upload (0 to 5s) - File uploaded
- Extract (4 to 30s) - Text extraction from PDF
- Analyze (30 to 90s) - AI analysis (contact, skills, experience)
- Chunk and Embed (90 to 120) - Chunk, Store and Embed document
Total time: 30 to 90 seconds for most CVs (up to 120s for complex documents)
Complete Example
cURL
curl -X POST "https://api.floreal.ai/v1/public/documents/upload-direct?documentName=John%20Doe%20-%20Software%20Engineer&documentType=cv&documentDate=11-2025" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/pdf" \
--data-binary @resume.pdfJavaScript (Node.js)
const fs = require('fs');
// Read file
const fileBuffer = fs.readFileSync('./resume.pdf');
// Upload
const params = new URLSearchParams({
documentName: 'John Doe - Software Engineer',
documentType: 'cv',
documentDate: '11-2025'
});
const response = await fetch(
'https://api.floreal.ai/v1/public/documents/upload-direct?' + params,
{
method: 'POST',
headers: {
'X-API-Key': 'YOUR_API_KEY',
'Content-Type': 'application/pdf'
},
body: fileBuffer
}
);
const result = await response.json();
console.log('✅ Uploaded! Document ID:', result.documentId);
// Poll for completion
const pollStatus = async (documentId) => {
const status = await fetch(
'https://api.floreal.ai/v1/public/documents/' + documentId,
{ headers: { 'Authorization': 'X-API-Key YOUR_API_KEY' } }
).then(r => r.json());
console.log('Status:', status.status);
if (status.status === 'completed') {
console.log('✅ Processing complete!');
console.log('Candidate:', status.contact);
return status;
}
if (status.status === 'failed' || status.status === 'invalid') {
console.error('❌ Processing failed:', status.error);
return status;
}
// Still processing
await new Promise(resolve => setTimeout(resolve, 5000));
return pollStatus(documentId);
};
await pollStatus(result.documentId);Python
import requests
import time
# Upload file
with open('resume.pdf', 'rb') as f:
response = requests.post(
'https://api.floreal.ai/v1/public/documents/upload-direct',
params={
'documentName': 'John Doe - Software Engineer',
'documentType': 'cv',
'documentDate': '11-2025'
},
headers={
'X-API-Key': 'YOUR_API_KEY',
'Content-Type': 'application/pdf'
},
data=f
)
data = response.json()
document_id = data['documentId']
print(f"✅ Uploaded! Document ID: {document_id}")
# Poll for completion
def poll_status(document_id):
while True:
status_response = requests.get(
f'https://api.floreal.ai/v1/public/documents/{document_id}',
headers={'Authorization': 'X-API-Key YOUR_API_KEY'}
)
status = status_response.json()
print(f"Status: {status['status']}")
if status['status'] == 'completed':
print("✅ Processing complete!")
print(f"Candidate: {status.get('contact', {})}")
return status
if status['status'] in ['failed', 'invalid']:
print(f"❌ Processing failed: {status.get('error', {})}")
return status
time.sleep(5)
poll_status(document_id)Error Responses
| Status | Error | Cause | Solution |
|---|---|---|---|
| 400 | Missing document name | No documentName query param | Add documentName query parameter |
| 400 | Missing content type | No Content-Type header | Add Content-Type header |
| 400 | Missing document date | No documentDate query param | Add documentDate query parameter |
| 400 | Invalid file type | Unsupported content type | Use PDF, DOC, DOCX, or TXT |
| 400 | File too large | File exceeds 10MB | Compress or split document |
| 400 | Invalid date format | Wrong date format | Use MM-YYYY (e.g., "11-2025") |
| 401 | Unauthorized | Invalid API key | Check Authorization header |
| 500 | Upload failed | Server error | Retry or contact support |
Validation & Limits
File Requirements
✅ Size: Maximum 10 MB ✅ Types: PDF, DOC, DOCX, TXT only ✅ Content: Must be a valid CV/resume ✅ Auto-conversion: DOC/DOCX files converted to PDF automatically
Metadata Requirements
✅ Document Name: 1 to 255 characters ✅ Document Date: MM-YYYY format (e.g., "03-2024") ✅ Document Type: "cv" or "other" (default: "cv")
Comparison: Upload Methods
| Feature | Direct Upload | Presigned URL | URL Fetch |
|---|---|---|---|
| Requests | 1 request | 3 requests | 1 request |
| Complexity | ⭐ Simple | ⭐⭐⭐ Complex | ⭐ Simple |
| File Source | Local file | Local file | Remote URL |
| Bandwidth | Uses API | Direct to S3 | Server fetches |
| Best For | Quick integration | Large files | Automation |
Recommendation: Use Direct Upload for most cases - it's the simplest and fastest method.
Security
✅ API Key Required - All requests authenticated ✅ Organization Scoped - Files isolated per company ✅ Temporary Storage - Files in temp folder until validated ✅ Automatic Cleanup - Temp files deleted after processing ✅ Automatic Sanitization - Filenames cleaned ✅ No Public Access - Files not publicly accessible ✅ HTTPS Only - Encrypted in transit ✅ Audit Trail - All uploads tracked in timeline
Monitoring & Debugging
Check Upload Status
curl -X GET https://api.floreal.ai/v1/public/documents/DOCUMENT_ID \
-H "X-API-Key: YOUR_API_KEY"List Recent Uploads
curl -X GET "https://api.floreal.ai/v1/public/documents?limit=10&sortOrder=desc" \
-H "X-API-Key: YOUR_API_KEY"Common Issues
Issue: "File uploaded but processing stuck in 'uploading'" Solution: Step Functions workflow may be delayed - wait up to 2 minutes
Issue: "Processing stuck in 'pending' for greater than 90 seconds" Solution: Check Step Functions logs or contact support
Issue: "Document marked as 'invalid' but is a CV" Solution: AI didn't recognize it as CV - check format/content quality
Issue: "DOCX upload works but DOC fails" Solution: DOC conversion may have issues - convert to PDF first
Next Steps
- ✅ Upload file using this endpoint
- ✅ Save documentId from response
- ✅ Poll status every 5 to 10 seconds
- ✅ Wait for completion (30 to 60 seconds typical)
- ✅ Retrieve data once status is
completed - ✅ Start searching using Search API
Related Endpoints
- Get Document -
GET /v1/public/documents/\{documentId\}- Check status and retrieve data - List Documents -
GET /v1/public/documents- Browse all uploads - Delete Document -
DELETE /v1/public/documents/\{documentId\}- Remove CV - Search CVs -
POST /v1/public/search- Find candidates
API key for public API access. Get yours at https://app.floreal.ai?tab=api
In: header
Query Parameters
1 <= length <= 255"cv""cv" | "other"^\d{2}-\d{4}$Response Body
curl -X POST "https://api.floreal.ai/v1/public/documents/upload-direct?documentName=string&documentType=cv&documentDate=string"{
"documentId": "789e4567-e89b-12d3-a456-426614174000",
"status": "uploading",
"message": "Document uploaded and processing started",
"documentUrl": "string",
"file": {
"name": "string",
"size": 0,
"sizeFormatted": "240 KB",
"contentType": "string"
},
"estimatedProcessingTime": "30 to 60 seconds",
"statusEndpoint": "/v1/public/documents/789e4567-e89b-12d3-a456-426614174000",
"nextSteps": [
"string"
]
}{
"error": "string",
"message": "string"
}{
"error": "string"
}{
"error": "string",
"message": "string"
}