Skip to content

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 url for upload
  • A fields dictionary 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

  1. Create a POST request using the url from the API response.
  2. In the Body tab, select form-data.
  3. Add each of the key-value pairs from the "fields" object.
  4. Add one more field named file and set its type to File — select the file to upload.
  5. 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_id is 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.