Errors & status codes

How failures are reported, and a checklist for handling them.

The APIs report outcomes in the JSON body, not only in the HTTP status line. Most endpoints answer HTTP 200 for every request and put the real outcome in the status field. Do not treat an HTTP 200 as success on its own.

The status field#

status follows HTTP conventions: 200 means the operation succeeded, 4xx means the request could not be processed as sent, 5xx means an upstream or server problem. Two things to be aware of:

  • Type varies by endpoint. Some endpoints return a number (200), some a string ("200"). Compare loosely (== 200) or cast first. Each reference page says which type its endpoint uses.
  • The message field varies too. Depending on the endpoint the explanation is in data (as a string), in message, or in an errors array. The reference pages show the exact shape.

Codes you will see#

status Meaning Typical cause
200 Success The operation completed. Check for an empty result before using it.
301 Not recognised YouTube Video Info: the URL did not contain a video id.
400 Bad request A required parameter is missing or malformed.
401 Unauthorised The Authorization: Bearer header is missing, or the key is invalid or expired.
401 Input unusable QR Decoder: the image URL was invalid, private, too large, or not decodable base64.
403 Forbidden The API key is not recognised, or (Drive) the file is not accessible.
406 Key expired Mail Verifier: renew the key with support.
422 Nothing found QR Decoder: the image loaded but held no readable QR code.
500 Server error The operation failed unexpectedly. Safe to retry once.
502 Upstream error A third-party service refused the request. Retry later.
503 Upstream unavailable Video Downloader: the extraction route is blocked. Retry later.
null Rejected Video endpoints: a required parameter or a valid key was missing.

Handling errors in code#

<?php
$json   = file_get_contents('https://api.zactonz.com/qr/dec/?image=' . rawurlencode($imageUrl));
$result = json_decode($json, true);

if (!is_array($result) || (int) ($result['status'] ?? 0) !== 200) {
    $reason = $result['data'] ?? $result['message'] ?? implode(', ', $result['errors'] ?? ['unknown']);
    throw new RuntimeException('QR decode failed: ' . $reason);
}
$text = $result['data'];

A short checklist:

  1. Parse the body as JSON. If parsing fails, the API is unreachable or returned an HTML error page; treat as a server error.
  2. Cast status to an integer and compare with 200.
  3. On failure, read the explanation from data, message or errors, whichever the endpoint uses.
  4. Retry only 5xx outcomes, with a delay. 4xx outcomes will fail again unchanged.