Upload API Documentation¶
Overview¶
The Upload API allows authenticated users to request a pre-signed S3 upload URL where they can upload files securely. It enforces plan-based restrictions, such as file size, total storage, pending uploads, and rate limits.
After generating an upload URL, the client can directly upload a file to S3 using the returned form data (POST upload).
Base URL:
https://api.apidatatools.com/upload-api
Endpoint (POST)¶
POST https://api.apidatatools.com/upload-api
Headers¶
| Header | Description | Required | Example |
|---|---|---|---|
Content-Type | Must be application/json | Yes | application/json |
x-api-key | User’s API key for authorization | Yes | abcdef1234567890 |
Request Body¶
| Field | Type | Required | Description | Example |
|---|---|---|---|---|
filename | String | Yes | The name of the file to upload, including its extension. Must be alphanumeric with optional _ or -. Only one . separating base and extension. | "report_2024.json" |
Allowed Extensions:
json, csv, xml, txt, yml, yaml, html, md, js, css, xls, xlsx, jpg, jpeg, png, gif, webp, sql, log
Example Request Body¶
{
"filename": "project_data.json"
}
Example Response¶
Successful Response¶
{
"upload_id": "upl_4c0a85f67aa74ecb95a9494a96e4a327",
"upload": {
"url": "https://my-upload-bucket.s3.amazonaws.com/",
"fields": {
"key": "user_123/upl_4c0a85f67aa74ecb95a9494a96e4a327/project_data.json",
"x-amz-meta-user-id": "user_123",
"x-amz-meta-upload-id": "upl_4c0a85f67aa74ecb95a9494a96e4a327",
"x-amz-meta-original-filename": "project_data.json",
"policy": "ey...base64...",
"x-amz-signature": "4e6b3..."
}
}
}
Explanation¶
The API response includes:
- A unique
upload_id - A pre-signed S3
urlfor upload - A
fieldsdictionary containing form fields that must be included in your upload request.
Uploading the File (Step 2)¶
Once you receive the presigned response, upload your file to S3.
The upload must be an HTTP POST multipart/form-data request with all provided fields included.
Example with curl¶
curl -X POST "https://my-upload-bucket.s3.amazonaws.com/" \
-F "key=user_123/upl_4c0a85f67aa74ecb95a9494a96e4a327/project_data.json" \
-F "x-amz-meta-user-id=user_123" \
-F "x-amz-meta-upload-id=upl_4c0a85f67aa74ecb95a9494a96e4a327" \
-F "x-amz-meta-original-filename=project_data.json" \
-F "policy=ey...base64..." \
-F "x-amz-signature=4e6b3..." \
-F "file=@/path/to/project_data.json"
Example with Postman¶
- Create a POST request using the
urlfrom the API response. - In the Body tab, select form-data.
- Add each of the key-value pairs from the
"fields"object. - Add one more field named
fileand set its type to File — select the file to upload. - Click Send.
Postman will POST the file directly using the presigned parameters.
Example with Python (requests)¶
import requests
# Step 1: Obtain the upload URL
api_url = "https://api.apidatatools.com/upload-api"
headers = {"Content-Type": "application/json", "x-api-key": "your_api_key"}
payload = {"filename": "project_data.json"}
r = requests.post(api_url, json=payload, headers=headers)
upload_info = r.json()["upload"]
# Step 2: Upload the file
files = {"file": open("project_data.json", "rb")}
r2 = requests.post(upload_info["url"], data=upload_info["fields"], files=files)
print("S3 response:", r2.status_code)
Example with JavaScript (fetch + FormData)¶
async function uploadFile(file) {
// Step 1: Request presigned URL
const res = await fetch("https://api.apidatatools.com/upload-api", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": "your_api_key"
},
body: JSON.stringify({ filename: file.name })
});
const { upload } = await res.json();
// Step 2: Prepare form data for S3 upload
const formData = new FormData();
for (const [key, value] of Object.entries(upload.fields)) {
formData.append(key, value);
}
formData.append("file", file);
// Step 3: Upload to S3
const s3Res = await fetch(upload.url, {
method: "POST",
body: formData
});
if (s3Res.ok) {
console.log("Upload successful!");
} else {
console.error("Upload failed:", s3Res.statusText);
}
}
Error Handling¶
| Error Code | HTTP Status | Description | Example |
|---|---|---|---|
UNAUTHORIZED | 401 | Invalid or missing API key | {"error":"UNAUTHORIZED","message":"Invalid auth"} |
USER_NOT_FOUND | 404 | Authenticated user not found | {"error":"USER_NOT_FOUND","message":"User not found"} |
INVALID_FILENAME_OR_EXTENSION | 400 | Filename is invalid or extension not supported | {"error":"INVALID_FILENAME_OR_EXTENSION","message":"Filename must contain only letters, numbers, dots, dashes or underscores"} |
RATE_LIMIT | 429 | Too many uploads per minute | {"error":"RATE_LIMIT","message":"Too many requests"} |
TOO_MANY_UPLOADS | 429 | Pending uploads limit reached | {"error":"TOO_MANY_UPLOADS","message":"Pending uploads limit reached."} |
QUOTA_EXCEEDED | 413 | Storage usage exceeds plan | {"error":"QUOTA_EXCEEDED","message":"Storage full. Please delete existing uploads."} |
INVALID_INPUT | 400 | Bad or malformed JSON body | {"error":"INVALID_INPUT","message":"Bad Input"} |
INVALID_PLAN | 403 | User’s plan not found or misconfigured | {"error":"INVALID_PLAN","message":"Plan 'basic' not found or misconfigured"} |
INTERNAL_ERROR | 500 | Unexpected server error | {"error":"INTERNAL_ERROR","message":"Failed to process your request"} |
Notes for Developers¶
- The upload API does not receive actual file content — only file metadata and the filename.
- File uploading happens directly to S3 using the returned presigned URL and form fields.
- Each
upload_idis unique and tracks pending uploads. - The S3 upload link expires after 5 minutes (
UPLOAD_METADATA_TTL = 300). - Allowed extensions and sizes depend on the user’s plan.
- Uploads beyond quota or invalid files will be rejected immediately.