{"openapi":"3.1.0","info":{"title":"Darkroom API","version":"1.0.0","description":"Analog darkroom and film maths as an API, computed locally and deterministically — the three corrections that bite when you develop film and make prints by hand. The reciprocity endpoint corrects long exposures for reciprocity failure, where film loses sensitivity past about a second: corrected time = metered^p (Schwarzschild p ≈ 1.3 for many films, settable per datasheet), so a metered 10-second exposure really wants about 20 seconds, a full stop more, while anything under the threshold is left untouched. The printexposure endpoint adjusts enlarger exposure when you change print size — light spreads as you raise the head, so exposure is proportional to (magnification + 1)², where magnification is print size ÷ negative size: going from 2× to 4× magnification turns a 10-second exposure into 27.8 seconds, about 1.5 stops, ready for f-stop printing. The pushpull endpoint scales development time for pushing or pulling film by N stops — time = base × factor^stops, roughly +40 % per stop pushed — turning a 7-minute base into 13.7 minutes at +2 stops, or 5 minutes pulled a stop. Everything is computed locally and deterministically, so it is instant and private. Ideal for film-photography and darkroom apps, light-meter and timer companions, lab and workshop tools, and analog-photography sites. Pure local computation — no key, no third-party service, instant. Live, nothing stored. 3 compute endpoints. For digital depth-of-field use a photography API; for lab molarity use a dilution API.","contact":{"name":"PremiumApi","url":"https://www.oanor.com/by/premiumapi"}},"servers":[{"url":"https://api.oanor.com/darkroom-api","description":"oanor gateway"}],"tags":[{"name":"Darkroom"},{"name":"Meta"}],"components":{"securitySchemes":{"oanorKey":{"type":"apiKey","in":"header","name":"x-oanor-key","description":"Get your key at https://www.oanor.com/developer/keys"}}},"security":[{"oanorKey":[]}],"paths":{"/v1/printexposure":{"get":{"operationId":"get_v1_printexposure","tags":["Darkroom"],"summary":"Enlarger exposure by magnification","description":"","parameters":[{"name":"old_time_seconds","in":"query","required":true,"description":"Current print exposure in seconds","schema":{"type":"string"},"example":"10"},{"name":"old_magnification","in":"query","required":true,"description":"Current magnification (print ÷ negative)","schema":{"type":"string"},"example":"2"},{"name":"new_magnification","in":"query","required":true,"description":"New magnification","schema":{"type":"string"},"example":"4"}],"security":[{"oanorKey":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"data":{"note":"When you raise the enlarger head for a bigger print the light spreads out, so exposure ∝ (magnification + 1)² (magnification = print size ÷ negative size). Adjust by the stops shown using your timer's f-stop mode, then fine-tune with a test strip — paper and focus drift matter too.","inputs":{"old_time_seconds":10,"new_magnification":4,"old_magnification":2},"stops_change":1.47,"exposure_ratio":2.778,"new_time_seconds":27.78},"meta":{"timestamp":"2026-06-06T15:30:47.099Z","request_id":"981d4382-06a1-4593-8884-73e54153ee3f"},"status":"ok","message":"Enlarger exposure","success":true}}}},"401":{"description":"Missing or invalid x-oanor-key header"},"402":{"description":"Active subscription required"},"429":{"description":"Rate-limit or monthly quota reached"},"502":{"description":"Upstream did not respond"}}}},"/v1/pushpull":{"get":{"operationId":"get_v1_pushpull","tags":["Darkroom"],"summary":"Push/pull development time","description":"","parameters":[{"name":"base_time_minutes","in":"query","required":true,"description":"Box-speed development time in minutes","schema":{"type":"string"},"example":"7"},{"name":"stops","in":"query","required":true,"description":"Stops to push (+) or pull (−)","schema":{"type":"string"},"example":"2"},{"name":"factor_per_stop","in":"query","required":false,"description":"Time factor per stop (default 1.4)","schema":{"type":"string"},"example":"1.4"}],"security":[{"oanorKey":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"data":{"note":"Pushing (rating film faster, then over-developing) or pulling scales development time by factor^stops — roughly +40 % per stop pushed is a common starting point, but it is film- and developer-specific, so trust the manufacturer's times where given. Pushing adds contrast and grain; pulling tames them.","inputs":{"stops":2,"factor_per_stop":1.4,"base_time_minutes":7},"direction":"push","developed_time_minutes":13.72},"meta":{"timestamp":"2026-06-06T15:30:47.185Z","request_id":"b92817a1-ce16-4606-8dc4-64099c4211ce"},"status":"ok","message":"Push/pull development","success":true}}}},"401":{"description":"Missing or invalid x-oanor-key header"},"402":{"description":"Active subscription required"},"429":{"description":"Rate-limit or monthly quota reached"},"502":{"description":"Upstream did not respond"}}}},"/v1/reciprocity":{"get":{"operationId":"get_v1_reciprocity","tags":["Darkroom"],"summary":"Reciprocity-failure correction","description":"","parameters":[{"name":"metered_seconds","in":"query","required":true,"description":"Metered exposure time in seconds","schema":{"type":"string"},"example":"10"},{"name":"schwarzschild_p","in":"query","required":false,"description":"Schwarzschild exponent (default 1.3)","schema":{"type":"string"},"example":"1.3"},{"name":"threshold_seconds","in":"query","required":false,"description":"Threshold below which no correction (default 1)","schema":{"type":"string"},"example":"1"}],"security":[{"oanorKey":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"data":{"note":"Reciprocity failure: above ~1 s most films lose sensitivity, so corrected time = metered^p (Schwarzschild p ≈ 1.3 for many films, but it is film-specific — check the datasheet). Below the threshold no correction is applied. Bellows/filter factors are separate and multiply on top.","inputs":{"metered_seconds":10,"schwarzschild_p":1.3,"threshold_seconds":1},"extra_stops":1,"extra_seconds":9.95,"corrected_seconds":19.95},"meta":{"timestamp":"2026-06-06T15:30:47.276Z","request_id":"b4c62720-c2f9-46d9-b758-789f700d55ee"},"status":"ok","message":"Reciprocity correction","success":true}}}},"401":{"description":"Missing or invalid x-oanor-key header"},"402":{"description":"Active subscription required"},"429":{"description":"Rate-limit or monthly quota reached"},"502":{"description":"Upstream did not respond"}}}},"/v1/meta":{"get":{"operationId":"get_v1_meta","tags":["Meta"],"summary":"Spec","description":"","parameters":[],"security":[{"oanorKey":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"data":{"notes":"Reciprocity t^p (p≈1.3, film-specific); enlarging exposure ∝ (mag+1)²; push/pull time × factor^stops (≈+40 %/stop). Estimates — always confirm with a test strip and the film/developer datasheet. For digital depth-of-field use a photography API; for lab molarity use a dilution API.","service":"darkroom-api","endpoints":{"GET /v1/meta":"This document.","GET /v1/pushpull":"Development time scaled for pushing or pulling film by N stops.","GET /v1/reciprocity":"Corrected exposure time for long film exposures (Schwarzschild).","GET /v1/printexposure":"Enlarger exposure change when magnification changes (inverse-square)."},"description":"Analog darkroom maths: reciprocity-failure correction, enlarger print-exposure adjustment by magnification, and push/pull development scaling."},"meta":{"timestamp":"2026-06-06T15:30:47.349Z","request_id":"bdedf3b7-9946-4ace-b312-42d7a73063b8"},"status":"ok","message":"Meta","success":true}}}},"401":{"description":"Missing or invalid x-oanor-key header"},"402":{"description":"Active subscription required"},"429":{"description":"Rate-limit or monthly quota reached"},"502":{"description":"Upstream did not respond"}}}}},"x-oanor-pricing":[{"slug":"free","name":"Free","price_cents_month":0,"monthly_call_quota":400,"rps_limit":2,"hard_limit":true},{"slug":"starter","name":"Starter","price_cents_month":460,"monthly_call_quota":11000,"rps_limit":6,"hard_limit":true},{"slug":"pro","name":"Pro","price_cents_month":1610,"monthly_call_quota":72000,"rps_limit":15,"hard_limit":true},{"slug":"mega","name":"Mega","price_cents_month":4880,"monthly_call_quota":240000,"rps_limit":36,"hard_limit":true}],"x-oanor-marketplace-url":"https://www.oanor.com/api/darkroom-api"}