GET /v1/jobs 400 unknown_parameter: a typo'd filter no longer widens

A misspelled query key on GET /v1/jobs, such as state for status, now returns 400 with a suggestion instead of a full unfiltered page. Handle it in TypeScript.

4 min readSume
All posts

GET /v1/jobs?state=failed does not return a page of failed jobs. It returns 400 unknown_parameter with the message Unknown query parameter: 'state'. Did you mean 'status'? The list route accepts limit, scope, run_id, thread_id, type, status and starting_after, and refuses any other query key.

Why the API is strict here

A dropped filter does not lose a field, it widens the result. The API source records that GET /v1/jobs?thread_id=... once answered 200 with every job in the workspace when the filter was not honored. A caller who narrowed a search then received a larger page that looked like an answer. Rejecting unknown keys makes the mistake loud.

The response body

The error carries details.errors, one entry for each unknown key, with path, loc (which is ["query", key] for a query string), type: "unknown_parameter" and a suggestion when a known key is within an edit distance of 2. details.accepted lists every valid key, sorted.

Example misspellings on GET /v1/jobs (read 2026-10-04)
You sentSuggestionOutcome
state=failedstatus400 unknown_parameter
runid=arun_1run_id400 unknown_parameter
cursor=abcnone within distance 2400 unknown_parameter, see details.accepted
status=failed(valid)200, one page of failed jobs

Handle it in a client

Treat this error as a bug in your code, not a retryable failure. Print the suggestion and stop. The helper below builds the query from a typed allow-list, so a typo fails at compile time before it reaches the API.

type JobsQuery = {
  limit?: number; scope?: "thread" | "workspace"; run_id?: string;
  thread_id?: string; type?: string; starting_after?: string;
  status?: "queued" | "processing" | "completed" | "failed" | "canceled";
};

export function jobsUrl(base: string, q: JobsQuery): string {
  const url = new URL("/v1/jobs", base);
  for (const [k, v] of Object.entries(q)) if (v !== undefined) url.searchParams.set(k, String(v));
  return url.toString();
}

console.log(jobsUrl("https://api.sume.com", { status: "failed", limit: 50 }));
// https://api.sume.com/v1/jobs?status=failed&limit=50

Paging

Results are newest first and capped at 100 for each page. When data.next_cursor is present, send it back as starting_after. That key is on the allow-list as well, so a paging loop is unaffected by the strict check.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume