Zamzar launched in 2006 and helped define online file conversion. Its API, while functional, reflects an older design era: Basic Auth with your API key as the username, async job polling, and separate download requests. For developers building modern applications, this pattern adds boilerplate without adding capability.

ChangeThisFile offers a synchronous REST API with Bearer token auth — the pattern every developer expects in 2026. If your Zamzar usage is "convert this file to that format," the migration is a straightforward code replacement with meaningful cost savings.

Why people migrate from Zamzar

Expensive entry-level API tier. Zamzar's free Test plan gives 100 credits with a 1MB file limit. Its Startup API plan is $25/month for 500 credits (5 cents each, then $0.05 per extra credit). ChangeThisFile's free tier gives 25/month at zero cost; the $29 Hobby plan covers 1,500 conversions, about 1.9 cents each.

Basic Auth with API key as username. Zamzar authenticates via HTTP Basic Auth, passing your API key as the username with an empty password. This works but is an unusual pattern that confuses developers and tooling. ChangeThisFile uses standard Bearer token auth.

Three-step async pattern. Zamzar requires: (1) POST a conversion job, (2) poll GET until status is successful, (3) GET the output file. ChangeThisFile returns the converted file in the initial POST response. Three calls become one.

Email-delivery legacy. Zamzar was originally built for email delivery of converted files. The API inherited this architecture. If you never needed email delivery, you're working around a design decision that wasn't made for your use case.

Who should stay on Zamzar: If you need email delivery of converted files, or if you work with specific legacy/niche formats that Zamzar supports but ChangeThisFile doesn't (e.g., AutoCAD DWG, specialized 3D formats). Zamzar's format catalog is genuinely broad for niche formats.

Cost comparison

Volume/monthZamzar API (1 credit per conversion)ChangeThisFileDifference
500 conversions$25 (Startup, 500)$29 (Hobby, 1,500/mo)Zamzar $4 cheaper
1,200 conversions$60 (Startup + 700 × $0.05)$29 (Hobby, 1,500/mo)ChangeThisFile $31 cheaper
5,000 conversions$199 (Growth $99 + 2,500 × $0.04)$99 (Startup, 6,000/mo)ChangeThisFile $100 cheaper
20,000 conversions$599 (Scale $299 + 10,000 × $0.03)$499 (Scale, 40,000/mo)ChangeThisFile $100 cheaper
100,000 conversions$2,999 (Scale + 90,000 × $0.03)$1,999 (Growth, 200,000/mo)ChangeThisFile $1,000 cheaper

Prices checked 2026-10-10. Zamzar: developers.zamzar.com/pricing (Test free, 100 credits, 1MB files; Startup $25/500, Growth $99/2,500, Scale $299/10,000; overage $0.05/$0.04/$0.03 per credit). Assumes one credit per conversion. ChangeThisFile plans from changethisfile.com/pricing; every plan hard-stops at its quota, so the ChangeThisFile column is the cheapest plan that covers the volume.

At 500 conversions a month Zamzar's Startup plan is $4 cheaper. From about 1,000 to 200,000 a month ChangeThisFile costs less, as long as each Zamzar conversion uses one credit.

API endpoint mapping

Zamzar actionChangeThisFile equivalent
POST /v1/jobs (create job)POST /v1/convert (full conversion)
GET /v1/jobs/{id} (poll status)Not needed — synchronous
GET /v1/files/{id}/content (download)Not needed — file in response body
Basic Auth (api_key as username)Authorization: Bearer ctf_sk_{key}
target_format: "pdf"data.target: "pdf"
source_file: (multipart upload)files["file"]: open("file.docx", "rb")
source_url: "https://..."Must download first, then POST file

Code migration: BEFORE and AFTER

# BEFORE: Zamzar (Basic Auth, async poll, separate download)
import requests
import time

ZAMZAR_KEY = 'your_zamzar_api_key'
ZAMZAR_URL = 'https://api.zamzar.com/v1'

# Step 1: Create conversion job
with open('report.docx', 'rb') as f:
    resp = requests.post(
        f'{ZAMZAR_URL}/jobs',
        auth=(ZAMZAR_KEY, ''),  # API key as username, empty password
        files={'source_file': f},
        data={'target_format': 'pdf'}
    )
job_id = resp.json()['id']

# Step 2: Poll until done
while True:
    job = requests.get(
        f'{ZAMZAR_URL}/jobs/{job_id}',
        auth=(ZAMZAR_KEY, '')
    ).json()
    if job['status'] == 'successful':
        file_id = job['target_files'][0]['id']
        break
    if job['status'] == 'failed':
        raise Exception(f'Conversion failed: {job}')
    time.sleep(3)

# Step 3: Download result
result = requests.get(
    f'{ZAMZAR_URL}/files/{file_id}/content',
    auth=(ZAMZAR_KEY, ''),
    stream=True
)
with open('report.pdf', 'wb') as f:
    for chunk in result.iter_content(chunk_size=1024):
        f.write(chunk)

# AFTER: ChangeThisFile (Bearer auth, synchronous)
import requests

response = requests.post(
    'https://changethisfile.com/v1/convert',
    headers={'Authorization': 'Bearer ctf_sk_your_key'},
    files={'file': open('report.docx', 'rb')},
    data={'target': 'pdf'}
)
with open('report.pdf', 'wb') as f:
    f.write(response.content)

Auth and token migration

  1. Get a ChangeThisFile API key: Visit changethisfile.com/v1/keys/free. No card required. Key format: ctf_sk_....
  2. Switch from Basic Auth to Bearer token: Replace auth=(ZAMZAR_KEY, '') with headers={'Authorization': f'Bearer {CTF_KEY}'}. This is the most common change across languages and HTTP clients.
  3. Update your .env file: Rename ZAMZAR_API_KEY to CTF_API_KEY.
  4. Remove polling logic: Delete the while True status-poll loop and the separate download call. Replace with a single response.content read after the POST.
  5. Handle URL-based inputs separately: If you pass source_url to Zamzar, you'll need to download the file first with requests.get(url) and write it to a temp file or BytesIO buffer before calling ChangeThisFile.

Rollback plan

Zamzar's API keys remain active until you cancel your subscription. A fast rollback:

  1. Set a CONVERTER_BACKEND environment variable. Your conversion function checks this and routes to either API.
  2. If you hit an unsupported format (HTTP 400 from ChangeThisFile), log the source→target pair and route those specific calls back to Zamzar while you investigate.
  3. Keep Zamzar active for 30 days after migration. Cancel once you've confirmed zero rollbacks.

The most common rollback trigger is a niche format — DWG, DXF, specialized 3D formats, or old proprietary document types. Audit your job history for these before switching.

Common migration questions

Zamzar supports 1,100+ formats. Does ChangeThisFile match that?
Zamzar's catalog is broader for niche/legacy formats. ChangeThisFile covers 1,000+ specific conversion routes for mainstream formats. If you're using CAD, 3D, or legacy proprietary formats, check coverage before migrating those routes.

Can I still use Zamzar's email delivery feature?
ChangeThisFile has no email delivery. If you use Zamzar's email-delivery workflow to send converted files to end users, that feature doesn't translate. You'd need to handle email delivery yourself (e.g., Resend, Mailgun) after calling ChangeThisFile.

Does ChangeThisFile support URL-based conversion like Zamzar's source_url?
No — ChangeThisFile requires file upload. Download the source file first, then POST it. Two HTTP calls instead of one, but the result is the same.

What's the file size limit?
ChangeThisFile's free tier supports up to 25MB. Zamzar's limits vary by plan and format. If you convert large files (video, archives), verify the size limits on your CTF plan before migrating those routes.

The migration removes more code than it adds — the polling loop and download step go away entirely. The authentication change from Basic to Bearer is a single-line swap. Get your free API key and test your most-used format pair before committing.