Stophy

Error Handling

All errors return a JSON body with a machine-readable code. Concurrency limits scale with your plan.

Failed requests return a non-2xx status and a JSON body with success: false.

{
  "success": false,
  "code": "INVALID_INPUT",
  "error": "videoUrl is required"
}

Prop

Type

Error codes

Both BAD_REQUEST and INVALID_INPUT return status 400 but mean different things. BAD_REQUEST is a schema problem: a missing required field or an unrecognized enum value. INVALID_INPUT means the body looked fine but the content was wrong, like a URL that points nowhere or a video without captions.

Prop

Type

Concurrency

The API limits how many requests you can have in flight at the same time, scaled by your plan. This caps parallelism, not total throughput. Fire requests as fast as you want; keep the number running concurrently under your limit.

Your plan is the highest credit pack you have ever purchased. Buying a smaller pack for extra credits never lowers it. Unauthenticated requests and accounts with no pack use the Free limit.

PlanConcurrency (in flight)
Free / no pack5
Starter15
Builder60
Pro150
Scale300

Every response carries your current concurrency state:

HeaderDescription
X-Concurrency-LimitMax simultaneous in-flight requests for your plan
X-Concurrency-RemainingIn-flight slots still available right now

Going over returns 429 CONCURRENCY_LIMITED. It clears as soon as one of your in-flight requests finishes, so lower your parallelism rather than waiting on a clock.

Versioning

The API is versioned in the URL path (/v1/). Breaking changes like removed fields, changed response shapes, or altered error codes will always move to a new version (/v2/) with advance notice. We may add new optional fields or new error codes to the current version without notice. Handle unknown error codes in your default or else branch so your code stays forward-compatible.

Handling errors

The SDKs throw a typed StophyError carrying status, code, the message, and requestId. Branch on code and let unknown codes fall through to the default case.

import { Stophy, StophyError } from "stophy";

const stophy = new Stophy({ apiKey: process.env.STOPHY_API_KEY! });

try {
  const { data } = await stophy.video({
    type: "details",
    videoUrl: "https://www.youtube.com/watch?v=D7liwdjvhWc",
  });
  console.log(data);
} catch (err) {
  if (!(err instanceof StophyError)) throw err;
  switch (err.code) {
    case "INSUFFICIENT_CREDITS":
      // top up from dashboard
      break;
    case "CONCURRENCY_LIMITED":
      // too many requests in flight; retry once one finishes
      break;
    case "UNAUTHORIZED":
      // check your API key
      break;
    default:
      console.error(err.status, err.code, err.message);
  }
}
import os
from stophy import Stophy, StophyError

stophy = Stophy(os.environ["STOPHY_API_KEY"])

try:
    result = stophy.video(
        type="details",
        video_url="https://www.youtube.com/watch?v=D7liwdjvhWc",
    )
    print(result["data"])
except StophyError as err:
    if err.code == "INSUFFICIENT_CREDITS":
        pass  # top up from dashboard
    elif err.code == "CONCURRENCY_LIMITED":
        pass  # too many requests in flight; retry once one finishes
    elif err.code == "UNAUTHORIZED":
        pass  # check your API key
    else:
        print(err.status, err.code, err)

For raw HTTP, read code off the JSON body when the response is non-2xx.

On this page