← Back to Portfolio
API Documentation · Portfolio Sample

Cat API — GET /v1/images/search

Specious Coda-Bishop · Technical Writing

Reference documentation for The Cat API's images search endpoint. Covers authentication, query parameters, response schema, error handling, and pagination behaviour — written to production documentation standards.

Portfolio Context

This document is a technical writing sample produced for a JetBrains application. The Cat API is a real, publicly available REST API. All parameters, response fields, error codes, and behaviour documented here reflect the actual API — this is not a fictional example.

The goal was to demonstrate API documentation to a production standard: precise parameter tables, accurate authenticated vs. unauthenticated distinctions, copy-pasteable examples, and error states written for resolution rather than enumeration.

01
Overview

The Cat API is a free, publicly available REST API for cat images and breed data. It's a genuinely useful tool for prototyping, testing, or building anything that needs placeholder imagery — and it happens to be cats, which is rarely a problem.

This document covers one endpoint: GET /v1/images/search. It's the one you'll use most. Send a request, get cat images back. By default it returns one random image — no setup, no key, nothing to configure. Once you add an API key, you unlock filtering by breed or category, pagination, and batch retrieval up to 25 results per request.

Common use cases

What you want to doHow to do it
Show a random cat image on a pageCall the endpoint with no parameters — one random image, no key required
Show only a specific breedUse breed_ids with an API key
Build a browsable gallery with pagesUse order=ASC, limit, and page to step through results in order
Show breed facts alongside the photoUse has_breeds=1 — the response will include a full breed data object
Only return still photos, no GIFsUse mime_types=jpg,png
Embed an image directly in an <img> tagSet format=src — the API returns the raw image file instead of JSON
02
Authentication

An API key is a unique string that identifies your account to the API. Think of it as a membership card — free to get, and it unlocks significantly more of the API than you can access without one.

You pass your API key in the request header as x-api-key. If you don't include it, the API still works — you just get one random image per call with no filtering. That's fine for a quick test. It's not enough to build anything real.

How to send the key

Header nameValue
x-api-keyYour API key, copied from the thecatapi.com dashboard

What the key unlocks

Without a keyWith a key
Images per request1Up to 25
Filter by breed or categoryNo — parameters are silently ignoredYes
PaginationNoYes
Monthly request allowanceNo limit, but no tracking either10,000 (free) / 100,000 (premium)
Watch out — casing matters

The header name must be lowercase: x-api-key. Some HTTP clients normalise header casing automatically, but not all of them. If your key appears valid but you're getting a 401, check that the header name isn't being sent as X-Api-Key or X-API-Key.

03
Base URL and Method
GET https://api.thecatapi.com/v1/images/search

GET is an HTTP method that means "give me data." You're not creating anything, not updating anything — you're just asking for cat images and the API is handing them back. All the options you want (how many images, which breed, what format) are added to the URL as query parameters after a ?, or passed as headers. There's no request body.

The URL above is the full path to the endpoint. Everything after the ? in your request is a query parameter — covered in the next section.

What's a query parameter?

A query parameter is a key-value pair appended to a URL to customise a request. The first one starts with ?; any additional ones are separated by &. For example: ?limit=10&order=ASC&breed_ids=beng passes three parameters at once. Order doesn't matter.

04
Query Parameters

These are the knobs you can turn to shape what the API gives back. None of them are required. Leave them all out and you get one random cat image — totally valid. Add them to get more specific.


How many and in what order

limit

Controls how many images come back in a single response. The default is 1. The maximum is 25. If you want more than one image, you need an API key.

When to use it: Any time you need more than a single cat — loading a grid, pre-fetching a batch, or building something that needs variety on the same page load.

ParameterTypeDefaultMaxRequires key?
limitinteger125Only for values above 1

order

Controls whether results come back in a stable, predictable sequence or in a random shuffle each time.

  • RANDOM (default) — different images every call. Good for widgets, splash screens, anything where novelty is the point. Pagination doesn't work in this mode.
  • ASC / DESC — results come back in a consistent order based on when the images were added to the API. Use either of these when you want to page through a stable result set — e.g. a gallery where users can go forward and back without seeing repeats.
ParameterTypeDefaultAccepted values
orderstringRANDOMRANDOM, ASC, DESC

page

When you're using order=ASC or order=DESC, you can step through the full result set in chunks using page. It's zero-indexed, so the first page is page=0, the second is page=1, and so on.

When to use it: Pagination. If you're fetching 10 images at a time and want the next 10, increment the page number. See Section 09 for a worked example.

Note: This parameter does nothing when order=RANDOM. The API ignores it silently.

ParameterTypeDefaultNote
pageinteger0Zero-indexed. Ignored when order=RANDOM.

Filtering by breed and category

breed_ids

Pass one or more breed IDs to get back images of only those breeds. IDs are short strings like beng for Bengal or abys for Abyssinian. Separate multiple IDs with a comma.

When to use it: When your app is about a specific breed, or when a user has selected a breed from a list and you're fetching images to match. To get the full list of valid breed IDs, call GET /v1/breeds.

Requires an API key. Without one, this parameter is silently ignored and you'll get a random image with no filtering applied.

ParameterTypeDefaultExample
breed_idsstringbreed_ids=beng,abys

category_ids

Similar to breed_ids, but for categories. Categories are broader groupings — things like "hats" or "boxes" — rather than breed-specific. Pass one or more category IDs as a comma-separated list. Call GET /v1/categories for the full list.

Requires an API key.

ParameterTypeDefaultExample
category_idsstringcategory_ids=1,5

has_breeds

By default, the API returns whatever images it finds — not all of them have breed data attached. Set has_breeds=1 to filter out any image that doesn't come with a breeds object in the response.

When to use it: Whenever you want to display breed information alongside the image — name, description, temperament, origin. Without this filter, the breeds array may come back empty even when you're not filtering by a specific breed.

ParameterTypeDefaultAccepted values
has_breedsinteger00 (off) or 1 (on)

Controlling the image itself

mime_types

The Cat API serves JPGs, PNGs, and GIFs. By default you'll get a mix of all three. Pass one or more types to restrict what comes back.

When to use it: If your UI can't handle GIFs, or you specifically want animated images, or you're compressing images downstream and need a consistent format.

ParameterTypeDefaultAccepted values
mime_typesstringAll typesjpg, png, gif (comma-separated)

size

The API stores images in multiple size variants. This parameter tells it which one to give you. med is a good default for most display contexts. Use thumb for compact grids or lists, and full when you need the original resolution.

ParameterTypeDefaultOptions (smallest → largest)
sizestringmedthumb, small, med, full

format

By default the API responds with JSON — a structured data object containing the image URL, dimensions, and any breed or category info. Setting format=src changes the response entirely: instead of JSON, you get back the raw image file itself.

When to use it: When you want to point an <img> tag directly at the API endpoint without any JavaScript. The endpoint URL becomes the image source. All other parameters still apply, so you can still filter by breed, type, or size.

ParameterTypeDefaultAccepted values
formatstringjsonjson, src
Heads up — filtering silently fails without a key

breed_ids and category_ids require a valid API key. Without one, these parameters are silently ignored — you won't get an error, just unfiltered results. If your filtering appears to have no effect, check that your x-api-key header is present and correct.

05
Request Example

The examples below use curl, a command-line tool for making HTTP requests. It comes pre-installed on macOS and Linux, and is available on Windows via WSL or Git Bash. You can paste these directly into a terminal — just replace YOUR_API_KEY with your actual key.

Authenticated request — 5 Bengal images with breed data

curl -X GET "https://api.thecatapi.com/v1/images/search?limit=5&has_breeds=1&breed_ids=beng&order=ASC&page=0" \
  -H "x-api-key: YOUR_API_KEY"

Here's what each part is doing:

PartWhat it does
curl -X GETMakes an HTTP GET request — reading data, not sending any
limit=5Return 5 images instead of the default 1
has_breeds=1Only return images that have breed data attached
breed_ids=bengFilter for Bengal cats only (beng is Bengal's ID in the API)
order=ASCReturn images in a consistent order so pagination works correctly
page=0Start from the first page of results (zero-indexed)
-H "x-api-key: ..."Sends the API key as a request header, which is required for filtering to work

Minimal unauthenticated request

No key, no parameters. Returns a single random cat image. Good for a quick check that the API is responding.

curl -X GET "https://api.thecatapi.com/v1/images/search"

Using format=src to embed directly

This returns the raw image file, not JSON. The URL below can be used as the src attribute of an <img> tag.

<!-- A random still cat photo, embedded directly with no JavaScript -->
<img src="https://api.thecatapi.com/v1/images/search?format=src&mime_types=jpg"
     alt="A random cat">
06
Response Schema

When format=json (the default), the API responds with a JSON array — a list of image objects, one per result. Even if you asked for only one image, it comes back as an array with a single item.

Understanding what fields come back — and when — saves debugging time. The breeds array, for example, is always present in the response, but it's empty unless you've asked for images with breed data attached.

Image Object

Every image in the response includes these fields.

FieldTypeWhat it contains
idstringA unique identifier for this image — useful if you want to request it directly later via GET /v1/images/{image_id}.
urlstringThe direct URL to the image file. This is what you'll put in an <img> tag or display to the user.
widthintegerImage width in pixels. Useful for calculating aspect ratios or setting container dimensions before the image loads.
heightintegerImage height in pixels.
breedsarrayA list of breed objects for this image. Empty ([]) if no breed data is attached. Use has_breeds=1 or breed_ids to guarantee this is populated.
categoriesarrayA list of category objects for this image. Empty ([]) if no categories are assigned or if you didn't filter by category_ids.

Breed Object (inside the breeds array)

When a breed is attached to an image, each item in the breeds array contains the following. Most images have either zero or one breed — multiple is uncommon.

FieldTypeWhat it contains
idstringThe breed's short identifier (e.g. beng). This is what you pass to breed_ids when filtering.
namestringThe breed's full name (e.g. Bengal).
descriptionstringA paragraph-length description of the breed's personality and characteristics.
temperamentstringA comma-separated list of personality traits (e.g. "Alert, Agile, Energetic, Demanding, Intelligent").
originstringThe country the breed originates from.
life_spanstringTypical lifespan as a range (e.g. "12 - 15", in years).
wikipedia_urlstringA link to the breed's Wikipedia article, if one is available.
reference_image_idstringThe ID of the canonical reference image for this breed. You can fetch it directly using GET /v1/images/{image_id}.

Pagination Header

When you use order=ASC or order=DESC, the API includes an extra HTTP response header alongside the JSON body.

HeaderWhat it tells you
pagination-countThe total number of images matching your current query — across all pages, not just the current one. Divide by your limit value to calculate how many pages exist.
Response headers vs response body

The pagination-count value arrives as an HTTP header, not inside the JSON. In curl, use the -i flag to see headers alongside the response body. In JavaScript, access it via response.headers.get('pagination-count').

07
Response Example

This is what the API returns for a request with has_breeds=1&breed_ids=beng&limit=1. The breeds array is populated with a full breed object. The categories array is empty because no category filter was applied.

[
  {
    /* The image's unique ID — use this to fetch it directly later */
    "id": "O3btzLlsRf",

    /* The actual image URL — put this in your img src */
    "url": "https://cdn2.thecatapi.com/images/O3btzLlsRf.jpg",

    "width": 1200,
    "height": 800,

    /* breeds is populated because we used has_breeds=1 */
    "breeds": [
      {
        "id": "beng",
        "name": "Bengal",
        "description": "Bengals are a lot of fun to live with, but they're
          definitely not the cat for everyone, or for first-time cat owners.
          Extremely active, curious, and always alert, nothing escapes
          their attention.",
        "temperament": "Alert, Agile, Energetic, Demanding, Intelligent",
        "origin": "United States",
        "life_span": "12 - 15",
        "wikipedia_url": "https://en.wikipedia.org/wiki/Bengal_(cat)",
        "reference_image_id": "O3btzLlsRf"
      }
    ],

    /* Empty because we didn't filter by category */
    "categories": []
  }
]
08
Error States

The API uses standard HTTP status codes. If something goes wrong, the status code tells you where to look first.

StatusWhat it meansMost likely causeWhat to do
400 Bad Request You've passed a parameter value the API doesn't recognise — for example order=NEWEST or size=large. Check the accepted values in Section 04. Typos in parameter values are the most common cause.
401 Unauthorized The API key is missing, malformed, or invalid. Also fires if the header name is wrong. Double-check: (1) the header is named x-api-key in lowercase, (2) the key value is copied exactly from your dashboard with no extra spaces, (3) you haven't accidentally committed a placeholder like YOUR_API_KEY.
429 Too Many Requests You've used up your monthly request allowance — 10,000 on the free tier. Upgrade to a premium plan, or wait until the start of the next billing month for the allowance to reset. If you're hitting this in development, consider caching responses locally rather than calling the API repeatedly.
500 Internal Server Error Something went wrong on the API's side. Your request was fine — the server had a problem. Wait a moment and try again. If it keeps happening, check thecatapi.com for any service status announcements. Use exponential backoff if you're retrying automatically — don't hammer a struggling server.
What is exponential backoff?

If a request fails and you retry automatically, don't retry immediately — wait a moment first, then progressively longer between each attempt. For example: wait 1 second, retry; wait 2 seconds, retry; wait 4 seconds, retry. This avoids flooding a server that's already struggling, and is considered standard practice for handling transient failures.

09
Notes
How Pagination Works

Pagination lets you fetch large result sets in manageable chunks instead of all at once. Here's how it works in practice.

Say you want to show all Bengal cat images, 10 at a time. Your first request looks like this:

?breed_ids=beng&order=ASC&limit=10&page=0

The response body gives you 10 images. The pagination-count response header tells you, say, 87 — meaning there are 87 Bengal images in total. That means 9 pages (⌈87 ÷ 10⌉ = 9). To get the next batch, increment page:

?breed_ids=beng&order=ASC&limit=10&page=1  # images 11–20
?breed_ids=beng&order=ASC&limit=10&page=2  # images 21–30
# ...and so on
Key Rule — order must not be RANDOM

Pagination only works when order is ASC or DESC. With RANDOM (the default), the API returns a different random set every time — there's no stable sequence to page through. Setting page=2 with order=RANDOM doesn't return the "second page of random results" — it just returns another random set and ignores page entirely.


Rate Limits

Rate limits on the Cat API are monthly, not per-second. You won't get throttled for making rapid requests — but you will run out of allowance if you make too many calls across the month.

  • Free tier: 10,000 requests per month
  • Premium tier: 100,000 requests per month

If you're building something in development and burning through requests quickly, cache the responses locally. Fetching the same breed's images over and over during testing is a quick way to hit your limit before anything is even deployed.


Authenticated vs. Unauthenticated — The Silent Failure Problem

The API doesn't error when you pass filtering parameters without a key — it just ignores them and returns a random image. This is the most common source of confusion when first using the API.

If you're getting random results when you expected filtered ones, and everything looks right in your code, the problem is almost always a missing or invalid x-api-key header. Check these in order:

  • Is the header present at all in the request?
  • Is it named x-api-key in lowercase?
  • Is the value your actual key from the dashboard, not a placeholder?
  • Is the environment variable or config file actually being read by your code?