Skip to content

API

The 35mm.org data API.

Films, developers and development times as JSON — every time with the datasheet or chart it was read from. Read-only, and no key is needed to start.

Quick start

Ask for the published times of a film in a developer. Everything lives under https://35mm.org/api/public/v1; answers are JSON with snake_case keys and ISO 8601 dates in UTC.

curl "https://35mm.org/api/public/v1/development-times?film=ilford-hp5-plus&developer=ilford-id-11"

Each time comes with its source: what kind it is, its title and its address as stored. Where none is recorded the fields are null — nothing is filled in. Only published data is served: drafts, suggestions and anything about people never are.

Keys

Anonymous requests need nothing. For a higher limit, ask for an API key and send it as a bearer token:

curl -H "Authorization: Bearer 35mm_…" "https://35mm.org/api/public/v1/films"

A key that is wrong or has been revoked is answered 401 — it is never quietly treated as anonymous. Keys are for servers and tools: do not put one in a web page, where anyone can read it.

Keys are issued by hand, on request.

Rate limits

  • Without a key: 60 requests a minute for each address.
  • With a key: its own allowance, 600 a minute unless agreed otherwise.
  • Past the limit the answer is 429 with a Retry-After header (seconds to wait). Every answer carries X-RateLimit-Limit and X-RateLimit-Remaining.

Addresses are counted in a cache and never stored. A key’s use is counted per day — a number, nothing more.

Attribution

Every response has an attribution object. Please link back to 35mm.org wherever you show our data — the url of a film, developer or time points at its page — and show each time’s source with it: a development time without its source is only a number.

The data has no stated licence yet. Link back, keep each time’s source with it, and ask if you are unsure.

Endpoints

All of them are GET. The examples below are real answers for a small test catalogue, not production data.

GET /films

Films, A to Z, each with its maker, formats and the number of published times.

curl "https://35mm.org/api/public/v1/films?manufacturer=ilford"
Parameters
ParameterMeaning
qSearch the name or the maker, ignoring punctuation: hp5, ilford hp5.
manufacturerA manufacturer’s slug, such as ilford.
formatA format’s slug, such as 135 or 120.
processThe process: bw, c41, e6, ecn2 …
typeThe kind of film: bw_negative, color_negative, color_reversal …
still_made1 for films still in production, 0 for the rest.
has_times1 for films with a published time, 0 for those without.
page, per_pageSee pagination below.
Example response
{
    "data": [
        {
            "id": 101,
            "slug": "ilford-hp5-plus",
            "name": "HP5 Plus",
            "full_name": "Ilford HP5 Plus",
            "manufacturer": {
                "slug": "ilford",
                "name": "Ilford"
            },
            "iso": 400,
            "type": "bw_negative",
            "process": "bw",
            "is_chromogenic_bw": false,
            "status": "in_production",
            "still_made": true,
            "formats": [
                {
                    "slug": "135",
                    "name": "35mm (135)"
                }
            ],
            "respool_of": null,
            "published_times_count": 2,
            "url": "https://35mm.org/film/ilford-hp5-plus",
            "api_url": "https://35mm.org/api/public/v1/films/ilford-hp5-plus",
            "updated_at": "2026-10-01T12:00:00Z"
        }
    ],
    "links": {
        "first": "https://35mm.org/api/public/v1/films?manufacturer=ilford&page=1",
        "last": "https://35mm.org/api/public/v1/films?manufacturer=ilford&page=1",
        "prev": null,
        "next": null
    },
    "meta": {
        "current_page": 1,
        "last_page": 1,
        "per_page": 50,
        "from": 1,
        "to": 1,
        "total": 1
    },
    "attribution": {
        "text": "Data from 35mm.org — each time with its source. Please link back to 35mm.org.",
        "url": "https://35mm.org"
    }
}

GET /films/{slug}

One film with its specification and every published development time.

curl "https://35mm.org/api/public/v1/films/ilford-hp5-plus"
Example response
{
    "data": {
        "id": 101,
        "slug": "ilford-hp5-plus",
        "name": "HP5 Plus",
        "full_name": "Ilford HP5 Plus",
        "manufacturer": {
            "slug": "ilford",
            "name": "Ilford"
        },
        "iso": 400,
        "type": "bw_negative",
        "process": "bw",
        "is_chromogenic_bw": false,
        "status": "in_production",
        "still_made": true,
        "formats": [
            {
                "slug": "135",
                "name": "35mm (135)"
            }
        ],
        "respool_of": null,
        "published_times_count": 2,
        "url": "https://35mm.org/film/ilford-hp5-plus",
        "api_url": "https://35mm.org/api/public/v1/films/ilford-hp5-plus",
        "updated_at": "2026-10-01T12:00:00Z",
        "base": null,
        "emulsion_type": null,
        "spectral_sensitivity": null,
        "has_remjet": false,
        "first_released_year": 1989,
        "discontinued_year": null,
        "grain_rms": 14.0,
        "resolving_power_lpmm": null,
        "dmax": null,
        "latitude_stops_under": null,
        "latitude_stops_over": null,
        "datasheet_url": null,
        "image_url": null,
        "development_times": [
            {
                "id": 501,
                "film": {
                    "slug": "ilford-hp5-plus",
                    "name": "HP5 Plus",
                    "url": "https://35mm.org/film/ilford-hp5-plus"
                },
                "developer": {
                    "slug": "ilford-id-11",
                    "name": "ID-11",
                    "url": "https://35mm.org/developer/ilford-id-11"
                },
                "dilution": {
                    "label": "Stock",
                    "is_stock": true
                },
                "format": "any",
                "ei": 400,
                "temperature_c": 20.0,
                "time_seconds": 450,
                "time": "7:30",
                "agitation": "10 s at the start, then 10 s every minute",
                "process_type": "tank",
                "confidence": "verified",
                "notes": "Tank, 10 s initial agitation.",
                "source": {
                    "type": "manufacturer_datasheet",
                    "title": "ILFORD HP5 PLUS technical information, 2023",
                    "url": "https://example.com/ilford-hp5-plus-datasheet.pdf"
                },
                "inherited_from": null,
                "url": "https://35mm.org/film/ilford-hp5-plus/developed-in/ilford-id-11",
                "updated_at": "2026-10-01T12:00:00Z"
            },
            {
                "id": 502,
                "film": {
                    "slug": "ilford-hp5-plus",
                    "name": "HP5 Plus",
                    "url": "https://35mm.org/film/ilford-hp5-plus"
                },
                "developer": {
                    "slug": "ilford-id-11",
                    "name": "ID-11",
                    "url": "https://35mm.org/developer/ilford-id-11"
                },
                "dilution": {
                    "label": "1+1",
                    "is_stock": false
                },
                "format": "any",
                "ei": 800,
                "temperature_c": 20.0,
                "time_seconds": 600,
                "time": "10:00",
                "agitation": null,
                "process_type": "tank",
                "confidence": "community",
                "notes": null,
                "source": {
                    "type": "community",
                    "title": null,
                    "url": null
                },
                "inherited_from": null,
                "url": "https://35mm.org/film/ilford-hp5-plus/developed-in/ilford-id-11",
                "updated_at": "2026-10-01T12:00:00Z"
            }
        ]
    },
    "attribution": {
        "text": "Data from 35mm.org — each time with its source. Please link back to 35mm.org.",
        "url": "https://35mm.org"
    }
}

GET /developers

Developers and other chemistry.

curl "https://35mm.org/api/public/v1/developers?manufacturer=ilford"
Parameters
ParameterMeaning
qSearch the name or the maker.
manufacturerA manufacturer’s slug.
typeThe kind of chemistry: bw_developer, c41_kit, fixer …
still_made1 for those still in production, 0 for the rest.
page, per_pageSee pagination below.
Example response
{
    "data": [
        {
            "id": 201,
            "slug": "ilford-id-11",
            "name": "ID-11",
            "full_name": "Ilford ID-11",
            "manufacturer": {
                "slug": "ilford",
                "name": "Ilford"
            },
            "type": "bw_developer",
            "form": "powder",
            "status": "in_production",
            "still_made": true,
            "reuse": "depends",
            "is_one_shot": false,
            "is_replenishable": null,
            "reuse_source": {
                "title": "ILFORD PERCEPTOL, ID-11 AND MICROPHEN FILM DEVELOPERS",
                "url": "https://www.ilfordphoto.com/wp/wp-content/uploads/2024/09/ILFORD-POWDER-CHEM-190824.pdf"
            },
            "published_times_count": 2,
            "url": "https://35mm.org/developer/ilford-id-11",
            "api_url": "https://35mm.org/api/public/v1/developers/ilford-id-11",
            "updated_at": "2026-10-01T12:00:00Z"
        }
    ],
    "links": {
        "first": "https://35mm.org/api/public/v1/developers?manufacturer=ilford&page=1",
        "last": "https://35mm.org/api/public/v1/developers?manufacturer=ilford&page=1",
        "prev": null,
        "next": null
    },
    "meta": {
        "current_page": 1,
        "last_page": 1,
        "per_page": 50,
        "from": 1,
        "to": 1,
        "total": 1
    },
    "attribution": {
        "text": "Data from 35mm.org — each time with its source. Please link back to 35mm.org.",
        "url": "https://35mm.org"
    }
}

GET /developers/{slug}

One developer with its dilutions and the films it has published times for.

curl "https://35mm.org/api/public/v1/developers/ilford-id-11"
Example response
{
    "data": {
        "id": 201,
        "slug": "ilford-id-11",
        "name": "ID-11",
        "full_name": "Ilford ID-11",
        "manufacturer": {
            "slug": "ilford",
            "name": "Ilford"
        },
        "type": "bw_developer",
        "form": "powder",
        "status": "in_production",
        "still_made": true,
        "reuse": "depends",
        "is_one_shot": false,
        "is_replenishable": null,
        "reuse_source": {
            "title": "ILFORD PERCEPTOL, ID-11 AND MICROPHEN FILM DEVELOPERS",
            "url": "https://www.ilfordphoto.com/wp/wp-content/uploads/2024/09/ILFORD-POWDER-CHEM-190824.pdf"
        },
        "published_times_count": 2,
        "url": "https://35mm.org/developer/ilford-id-11",
        "api_url": "https://35mm.org/api/public/v1/developers/ilford-id-11",
        "updated_at": "2026-10-01T12:00:00Z",
        "shelf_life_unopened_months": 24,
        "shelf_life_opened_months": 3,
        "capacity_rolls_per_litre": 10.0,
        "datasheet_url": null,
        "dilutions": [
            {
                "label": "Stock",
                "is_stock": true,
                "parts_developer": 1.0,
                "parts_water": 0.0
            },
            {
                "label": "1+1",
                "is_stock": false,
                "parts_developer": 1.0,
                "parts_water": 1.0
            }
        ],
        "films": [
            {
                "slug": "ilford-hp5-plus",
                "name": "HP5 Plus",
                "published_times_count": 2,
                "times_url": "https://35mm.org/api/public/v1/development-times?film=ilford-hp5-plus&developer=ilford-id-11"
            }
        ]
    },
    "attribution": {
        "text": "Data from 35mm.org — each time with its source. Please link back to 35mm.org.",
        "url": "https://35mm.org"
    }
}

GET /development-times

Search published times. A respool with no times of its own answers with its parent stock’s, marked inherited_from.

curl "https://35mm.org/api/public/v1/development-times?film=ilford-hp5-plus&developer=ilford-id-11&ei=400"
Parameters
ParameterMeaning
filmA film’s slug.
developerA developer’s slug.
dilutionA dilution’s label as published: Stock, 1+1 …
eiThe exposure index the film was rated at.
temperatureThe temperature in °C.
formatThe format the time is for: 135, 120, sheet or any.
page, per_pageSee pagination below.
Example response
{
    "data": [
        {
            "id": 501,
            "film": {
                "slug": "ilford-hp5-plus",
                "name": "HP5 Plus",
                "url": "https://35mm.org/film/ilford-hp5-plus"
            },
            "developer": {
                "slug": "ilford-id-11",
                "name": "ID-11",
                "url": "https://35mm.org/developer/ilford-id-11"
            },
            "dilution": {
                "label": "Stock",
                "is_stock": true
            },
            "format": "any",
            "ei": 400,
            "temperature_c": 20.0,
            "time_seconds": 450,
            "time": "7:30",
            "agitation": "10 s at the start, then 10 s every minute",
            "process_type": "tank",
            "confidence": "verified",
            "notes": "Tank, 10 s initial agitation.",
            "source": {
                "type": "manufacturer_datasheet",
                "title": "ILFORD HP5 PLUS technical information, 2023",
                "url": "https://example.com/ilford-hp5-plus-datasheet.pdf"
            },
            "inherited_from": null,
            "url": "https://35mm.org/film/ilford-hp5-plus/developed-in/ilford-id-11",
            "updated_at": "2026-10-01T12:00:00Z"
        }
    ],
    "links": {
        "first": "https://35mm.org/api/public/v1/development-times?film=ilford-hp5-plus&developer=ilford-id-11&ei=400&page=1",
        "last": "https://35mm.org/api/public/v1/development-times?film=ilford-hp5-plus&developer=ilford-id-11&ei=400&page=1",
        "prev": null,
        "next": null
    },
    "meta": {
        "current_page": 1,
        "last_page": 1,
        "per_page": 50,
        "from": 1,
        "to": 1,
        "total": 1
    },
    "attribution": {
        "text": "Data from 35mm.org — each time with its source. Please link back to 35mm.org.",
        "url": "https://35mm.org"
    }
}

A development time

The fields of a development time
FieldMeaning
time_seconds, timeThe time in whole seconds, and as m:ss.
ei, temperature_cThe exposure index and the temperature in °C the time is for.
sourceAlways present: type (manufacturer_datasheet, own_test, third_party, community), title and url as stored — null where none is recorded.
confidenceverified, community, unverified or disputed: how far the time has been checked against its source.
inherited_fromThe slug of the parent stock when a respool takes its times, otherwise null.

Paging

Lists are paged with page and per_page (50 by default, at most 100). links has the first, last, prev and next addresses — null where there is none — and meta has current_page, last_page, per_page, from, to and total. Follow links.next until it is null.

Caching

Answers carry ETag and Last-Modified and Cache-Control: public, max-age=300. Send the ETag back in If-None-Match and an unchanged answer returns 304 with no body — it is still counted as a request. Please cache on your side too: the catalogue does not change by the minute.

Browsers on any site may read these routes (CORS: GET from any origin).

Errors

Errors share one shape, with details for a refused parameter:

{
    "error": {
        "code": "invalid_parameter",
        "message": "One or more parameters are not valid.",
        "details": { "per_page": ["The per page field must not be greater than 100."] }
    }
}
Errors
HTTPcodeMeaning
401invalid_api_keyThe key is wrong or has been revoked.
404not_foundNo film or developer with that slug.
405method_not_allowedThe API is read-only: use GET.
422invalid_parameterA parameter is not a valid value.
429rate_limitedToo many requests: wait for Retry-After seconds, or ask for a key.

OpenAPI

The whole API is described in an OpenAPI 3.1 file: /api/public/v1/openapi.json. Import it into Postman, Insomnia or a code generator.

Embed a time card

Blogs and forums can show one development time as a small card: film, developer, dilution, speed, temperature, the time and its source, with a link back to 35mm.org. It is a plain page — no cookies, no scripts, nothing loaded from other sites — made to be framed.

<iframe src="https://35mm.org/embed/time?film=ilford-hp5-plus&developer=ilford-id-11&dilution=Stock&ei=400&temp=20" width="100%" height="214" style="border:0;max-width:440px" loading="lazy" title="HP5 Plus in ID-11 — 35mm.org"></iframe>
Parameters
ParameterMeaning
film, developerThe film’s and the developer’s slugs.
dilution, ei, tempNarrow it down to one time. Left out, the time at box speed is shown.
idOr one time by its id, from the API.
themelight or dark. Left out, the card follows the reader’s colour scheme.
langen, pl or uk.

If no published time matches, the card says so and links to the film — it never shows a near match. The Embed button on any film × developer page makes the code for you, with a preview.

We count how often a card is shown, per day, per site (the host of the page it is on, nothing longer) and per combination. No cookies, no addresses.