Authentication
API keys, getting a free key, and security best practices.
The ChangeThisFile API uses bearer tokens. Every request to /v1/* (except POST /v1/keys/free) must include an Authorization header:
Authorization: Bearer ctf_sk_...your_key_here...API key format #
| Prefix | Meaning |
|---|---|
ctf_sk_… | Standard secret key — server-side use only. Full read/write access to your account. |
whsec_… | Webhook signing secret. Returned by POST /v1/webhooks/secret. Not an API key — used to verify HMAC signatures on incoming webhooks. |
Keys never expire automatically. Rotate them from the dashboard or via POST /v1/keys/rotate.
Get a free key #
curl -X POST https://changethisfile.com/v1/keys/free \
-H "Content-Type: application/json" \
-d '{"email":"you@example.com"}'Response (key shown once — store it now):
{
"api_key": "ctf_sk_...full_key...",
"plan": "free",
"monthly_limit": 1000,
"message": "Save this key — it will not be shown again."
}The free tier includes 1,000 conversions/month, a 25 MB file cap, and a 10 req/min throttle. Upgrade via POST /v1/billing/checkout or in the dashboard.
Security best practices #
Never expose secret keys in client-side code
ctf_sk_… keys grant full account access. Always proxy through your backend — never embed them in browser bundles, mobile apps, or any code your end users can inspect. If a key leaks, rotate it immediately.
Use environment variables, not config files
Store keys in environment variables (e.g. CTF_API_KEY) and load them at runtime — never hard-code them in source files that might end up in a public repo.
export CTF_API_KEY="ctf_sk_..."
curl -X POST https://changethisfile.com/v1/convert \
-H "Authorization: Bearer $CTF_API_KEY" \
-F "file=@photo.png" -F "target=jpg" -o photo.jpgRotate after every leak — and on a schedule
Suspect a key was logged, pushed to a public repo, or pasted in chat? Rotate it. The dashboard supports zero-downtime rotation: create a new key, deploy it, then revoke the old one. We recommend rotating on a quarterly cadence at minimum.
Verify every webhook signature
Webhook URLs are publicly reachable by definition. Always verify X-CTF-Signature with constant-time HMAC compare before trusting the payload — and reject timestamps older than 5 minutes. See Webhooks for ready-to-paste snippets in Python, Node, and PHP.
Set tight HTTP timeouts on your callers
The conversion endpoint streams large binaries — don't let a stuck upstream hang your worker. Set a per-request timeout of 60-600s based on the largest file you'll process.
Auth errors #
| Status | error.code | What it means |
|---|---|---|
401 | invalid_api_key | Header missing, malformed, or revoked key. Re-issue from the dashboard. |
429 | quota_exceeded | Monthly conversion quota hit. Free tier hard-stops; paid tiers fall through to overage at the per-conversion rate. |
429 | rate_limited | Too many requests in a 60-second window. Honor the Retry-After header. |