KosherFish Developer API

KosherFish offers a free, public, read-only API so developers can use kosher-fish data in their own apps and sites. It answers the same question the website does, in JSON: is this fish kosher?

The basics

  • Base URL: https://api.kosherfish.co
  • Cost: free. No API key is needed for any read request.
  • Method: read-only. Every data endpoint is a GET request.
  • Format: JSON, shaped { "success": true, "data": ... }.
  • Coverage: hundreds of fish species, cross-referenced with the Orthodox Union and Chabad.

Interactive docs

Two built-in references make it easy to explore:

  • Swagger UI at https://api.kosherfish.co/docs lets you try each endpoint in the browser.
  • OpenAPI spec at https://api.kosherfish.co/openapi.json is the machine-readable definition for code generators.

Caching and ETags

Responses are cached and ETag-aware. If you send an If-None-Match header with the ETag from a prior response, you get a fast 304 Not Modified when nothing has changed. Watch the Cache-Control header to see how long a response stays fresh.

Endpoints

Here is the full list of endpoints, all under the base URL https://api.kosherfish.co. Every data response is shaped { "success": true, "data": ... }.

Fish

  • GET /api/v1/fish · list or filter fish. Query parameters: q (search common name, scientific name, or alias), kosher (true or false), category, limit (default 100, max 500), and offset. The response includes a meta block with total, limit, and offset.
  • GET /api/v1/fish/all · every fish in one cached list.
  • GET /api/v1/fish/{id} · one fish by its numeric id. Returns 404 if the id does not exist.
  • GET /api/v1/search?q= · ranked search with a fuzzy fallback, so close spellings still match. Returns a match_score and a mode of exact or fuzzy.
  • GET /api/v1/suggest?q= · lightweight autocomplete, capped at 8 results, for typeahead UIs.

Meta

  • GET /health · liveness check. Returns { "status": "ok", "timestamp": ... }.
  • GET /api/v1/categories · the list of categories with a count for each.
  • GET /api/v1/stats · dataset counts: total, kosher, notKosher, withImages, and withAttribution.

Images and docs

  • GET /images/{key} · a fish illustration, served WebP-negotiated with a long cache.
  • GET /docs · the interactive Swagger UI.
  • GET /openapi.json · the OpenAPI 3.0 spec.

What a fish record contains

A fish object includes id, name, scientific_name, hebrew_name, aliases, is_kosher, kosher_notes, has_fins, has_scales, description, category, image_key, and a built image_url.

Example calls

Here are copy-paste examples to get you started. They use curl, but any HTTP client works the same way. No API key is needed.

Is salmon kosher?

curl "https://api.kosherfish.co/api/v1/search?q=salmon"

This runs a ranked search and returns the matching fish with their kosher status.

List non-kosher fish

curl "https://api.kosherfish.co/api/v1/fish?kosher=false&limit=10"

This filters to species that fail the fins-and-scales test, ten at a time.

Get one fish by id

curl "https://api.kosherfish.co/api/v1/fish/42"

This returns the full record for the fish with id 42, or a 404 if there is none.

Autocomplete suggestions

curl "https://api.kosherfish.co/api/v1/suggest?q=tun"

This returns up to eight quick suggestions, handy for a search-as-you-type box.

Dataset stats

curl "https://api.kosherfish.co/api/v1/stats"

This returns the counts of total, kosher, and non-kosher fish, plus how many have images.

A polite cached request

curl -H 'If-None-Match: "the-etag-from-last-time"' "https://api.kosherfish.co/api/v1/fish/all"

If nothing changed, you get a fast 304 Not Modified and save the bandwidth.

Rate limits and fair use

The API is free, and a few hundred requests a minute is fine for normal use. There is one limit to keep the service healthy for everyone.

Each IP address can make up to 240 requests per minute. Go past that and you get a 429 Too Many Requests response with a Retry-After header telling you how many seconds to wait.

  • X-RateLimit-Limit · the cap, 240.
  • X-RateLimit-Remaining · how many requests you have left this minute.
  • Retry-After · on a 429, the seconds to wait before trying again.

Cache responses on your end and use ETags with If-None-Match to get cheap 304 responses. If you need the full dataset, call /api/v1/fish/all once and cache it rather than looping through individual fish. That keeps you well under the limit and keeps the API fast for everyone.

Scroll to Top
This is a guide, not a halachic ruling. When in doubt, ask a trusted rabbi.