On this page

API

Conditional requests and caching

ETag and If-None-Match make repeat reads cheap, If-Match makes concurrent item edits safe, and the Cache-Control headers say what a cache may keep.

Cheap re-reads: ETag and If-None-Match

get_item and get_openapi_document return a strong ETag. Send it back as If-None-Match and an unchanged resource answers 304 Not Modified with no body, which is quick and does not cost more than a normal read in your rate limit. Archive downloads (get_version_archive) also answer 304 to If-None-Match.

curl

bash
curl -i https://reuseforge.com/api/v1/items/acme/invoice-extractor      # note the ETag header
curl -i https://reuseforge.com/api/v1/items/acme/invoice-extractor -H 'If-None-Match: "3f9a0c1d7b2e4a65"'   # 304 if unchanged

Python

python
import reuseforge

client = reuseforge.Client()
item = client.get_item("acme/invoice-extractor")
etag = client.last_response.etag
again = client.get_item("acme/invoice-extractor", etag=etag)     # None when the server answered 304

JavaScript

javascript
import { ReuseForge } from '@reuseforge/sdk';

const client = new ReuseForge();
const item = await client.getItem('acme/invoice-extractor');
const etag = client.lastResponse.etag;
const again = await client.getItem('acme/invoice-extractor', { etag });   // null when the server answered 304

An ETag is a validator, not a version number: treat it as an opaque quoted string.

Safe edits: If-Match

update_item is a partial update that requires If-Match with the ETag you last read. That makes concurrent edits safe without version fields:

SituationAnswer
If-Match matches the current ETagThe update is applied. The new item and a new ETag come back.
If-Match is stale412 precondition_failed with current_etag. Re-read, merge, send again.
If-Match is missing428 precondition_required.

curl

bash
ETAG=$(curl -sI https://reuseforge.com/api/v1/items/acme/invoice-extractor | awk 'tolower($1)=="etag:" {print $2}' | tr -d '\r')
curl -X PATCH https://reuseforge.com/api/v1/items/acme/invoice-extractor \
  -H "Authorization: Bearer $REUSEFORGE_TOKEN" -H "If-Match: $ETAG" -H "Content-Type: application/json" \
  -d '{"summary": "Extracts totals and line items from PDF invoices."}'

Python

python
item = client.update_item("acme/invoice-extractor", {"summary": "Extracts totals and line items."}, if_match="auto")   # reads the ETag first

JavaScript

javascript
await client.updateItem('acme/invoice-extractor', { summary: 'Extracts totals and line items.', ifMatch: 'auto' });   // reads the ETag first

CLI

bash
rf items update acme/invoice-extractor --summary 'Extracts totals and line items.'      # reads the ETag itself and sends If-Match

In the SDKs a 412 is a ConflictError whose current_etag (currentEtag in JavaScript) is the value to retry with. if_match="auto" is a convenience for scripts: it reads, then writes, so use an explicit ETag when you want to detect edits made between your own read and your write.

What caches may keep

ResponseCache-Control
Anonymous GET of a public resourcepublic, max-age=15, s-maxage=30, stale-while-revalidate=60
Anything authenticatedprivate, no-cache
Money and order endpoints, token secretsno-store
Free public version archivespublic, max-age=300; the bytes never change, but access can (a retraction must reach caches soon)

Every JSON response also sends X-Content-Type-Options: nosniff and Vary: Authorization, Accept-Encoding, so a shared cache never serves a signed-in response to an anonymous caller. Cross-origin browsers can read ETag, Link, RateLimit-*, Retry-After, X-Request-Id, ReuseForge-Version, Idempotent-Replayed and Location; preflights allow Authorization, Content-Type, Idempotency-Key, If-Match and If-None-Match.

Last updated: