{"id":"providers/smithsonian-open-access","relativePath":"providers/smithsonian-open-access.md","title":"Smithsonian Open Access Integration Plan","markdown":"# Smithsonian Open Access Integration Plan\n\nStatus: Landed + constraint-hardened (B5 provider slice)  \nUpdated: May 30, 2026\n\n## Official sources\n\n- API docs landing: <https://api.si.edu/openaccess/docs/>\n- API key signup: <https://api.data.gov/signup/>\n- Open Access program overview: <https://www.si.edu/openaccess>\n\n## Key platform facts (from official docs)\n\n- Smithsonian Open Access API requires an `api_key` for endpoint access.\n- Core endpoints:\n  - `GET /openaccess/api/v1.0/search`\n  - `GET /openaccess/api/v1.0/category/:cat/search`\n  - `GET /openaccess/api/v1.0/content/:id`\n  - `GET /openaccess/api/v1.0/terms/:category`\n  - `GET /openaccess/api/v1.0/stats`\n- Search paging:\n  - `start` (offset)\n  - `rows` (1..1000, default 10)\n  - `sort`: `relevancy|id|newest|updated|random`\n- Route validation keeps `rowGroup` explicit and enum-limited to `objects|archives`.\n- Route validation keeps `category` explicit and enum-limited to official category paths.\n\n## Integration goals\n\n- Add Smithsonian as a first-class B5 provider under `provider-interface`.\n- Preserve canonical Linked Art JSON-LD at storage boundary (`SourceRecord` + `_source.raw`).\n- Keep API-key handling secure (env-only, no logging, no persistence).\n\n## Proposed implementation slice\n\n### Adapter (implemented)\n\n- `src/adapters/smithsonian.ts`\n  - profile descriptor\n  - search request builder (`q/start/rows/sort/type/row_group`)\n  - content fetch by `id/url`\n  - normalizer into project record/artwork boundaries\n\n### Routes (implemented)\n\n- `GET /api/smithsonian/profile`\n- `POST /api/smithsonian/search`\n- `POST /api/smithsonian/content`\n- `POST /api/smithsonian/import`\n\n### UI (implemented)\n\n- add `smithsonian` source toggle in `/explore`\n- provider attribution + rights/reuse display on results/details\n\n## Env configuration\n\n- `SMITHSONIAN_API_BASE` (default: `https://api.si.edu/openaccess/api/v1.0`)\n- `SMITHSONIAN_API_KEY` (required for live endpoint calls)\n\n## Security requirements\n\n- Never commit/share `SMITHSONIAN_API_KEY`.\n- Never emit the key in logs or error responses.\n- Keep outbound calls server-side only (no client-exposed key).\n\n## Standards mapping + tests\n\nRequired rounds (minimum): object/provenance/shared-structure + protocol/search rounds.\n\nRequired tests (failing-first):\n\n- `tests/adapters/smithsonian.test.ts`\n- `tests/api/smithsonian/profile.test.ts`\n- `tests/api/smithsonian/search.test.ts`\n- `tests/api/smithsonian/content.test.ts`\n- `tests/api/smithsonian/import.test.ts`\n\nProtocol checks (B8):\n\n- OPTIONS/CORS behavior on new routes\n- response shape conformance\n- URI opacity + array-cardinality safety where applicable\n\n## Exit criteria\n\n- Adapter + routes + tests green.\n- `/explore` can search/import Smithsonian records.\n- PR includes Standards Mapping note with round + fixture anchor coverage.\n\n## Constraint hardening notes\n\n- `SMITHSONIAN_API_KEY` is required for search/content/import fetches to Smithsonian endpoints.\n- `/api/smithsonian/search` route-level schema validates official pagination fields:\n  - `start` integer `>= 0`\n  - `rows` integer `1..1000`\n- Backward-compatible aliases (`offset`/`limit`) remain accepted for older internal callers, but `start`/`rows` are canonical.\n","sections":[{"level":2,"heading":"Official sources","anchor":"official-sources"},{"level":2,"heading":"Key platform facts (from official docs)","anchor":"key-platform-facts-from-official-docs"},{"level":2,"heading":"Integration goals","anchor":"integration-goals"},{"level":2,"heading":"Proposed implementation slice","anchor":"proposed-implementation-slice"},{"level":3,"heading":"Adapter (implemented)","anchor":"adapter-implemented"},{"level":3,"heading":"Routes (implemented)","anchor":"routes-implemented"},{"level":3,"heading":"UI (implemented)","anchor":"ui-implemented"},{"level":2,"heading":"Env configuration","anchor":"env-configuration"},{"level":2,"heading":"Security requirements","anchor":"security-requirements"},{"level":2,"heading":"Standards mapping + tests","anchor":"standards-mapping-tests"},{"level":2,"heading":"Exit criteria","anchor":"exit-criteria"},{"level":2,"heading":"Constraint hardening notes","anchor":"constraint-hardening-notes"}],"html":"<h1 id=\"smithsonian-open-access-integration-plan\">Smithsonian Open Access Integration Plan</h1>\n<p>Status: Landed + constraint-hardened (B5 provider slice)  </p>\n<p>Updated: May 30, 2026</p>\n<h2 id=\"official-sources\">Official sources</h2>\n<ul><li>API docs landing: &lt;https://api.si.edu/openaccess/docs/&gt;</li><li>API key signup: &lt;https://api.data.gov/signup/&gt;</li><li>Open Access program overview: &lt;https://www.si.edu/openaccess&gt;</li></ul>\n<h2 id=\"key-platform-facts-from-official-docs\">Key platform facts (from official docs)</h2>\n<ul><li>Smithsonian Open Access API requires an `api_key` for endpoint access.</li><li>Core endpoints:</li><li>`GET /openaccess/api/v1.0/search`</li><li>`GET /openaccess/api/v1.0/category/:cat/search`</li><li>`GET /openaccess/api/v1.0/content/:id`</li><li>`GET /openaccess/api/v1.0/terms/:category`</li><li>`GET /openaccess/api/v1.0/stats`</li><li>Search paging:</li><li>`start` (offset)</li><li>`rows` (1..1000, default 10)</li><li>`sort`: `relevancy|id|newest|updated|random`</li><li>Route validation keeps `rowGroup` explicit and enum-limited to `objects|archives`.</li><li>Route validation keeps `category` explicit and enum-limited to official category paths.</li></ul>\n<h2 id=\"integration-goals\">Integration goals</h2>\n<ul><li>Add Smithsonian as a first-class B5 provider under `provider-interface`.</li><li>Preserve canonical Linked Art JSON-LD at storage boundary (`SourceRecord` + `_source.raw`).</li><li>Keep API-key handling secure (env-only, no logging, no persistence).</li></ul>\n<h2 id=\"proposed-implementation-slice\">Proposed implementation slice</h2>\n<h3 id=\"adapter-implemented\">Adapter (implemented)</h3>\n<ul><li>`src/adapters/smithsonian.ts`</li><li>profile descriptor</li><li>search request builder (`q/start/rows/sort/type/row_group`)</li><li>content fetch by `id/url`</li><li>normalizer into project record/artwork boundaries</li></ul>\n<h3 id=\"routes-implemented\">Routes (implemented)</h3>\n<ul><li>`GET /api/smithsonian/profile`</li><li>`POST /api/smithsonian/search`</li><li>`POST /api/smithsonian/content`</li><li>`POST /api/smithsonian/import`</li></ul>\n<h3 id=\"ui-implemented\">UI (implemented)</h3>\n<ul><li>add `smithsonian` source toggle in `/explore`</li><li>provider attribution + rights/reuse display on results/details</li></ul>\n<h2 id=\"env-configuration\">Env configuration</h2>\n<ul><li>`SMITHSONIAN_API_BASE` (default: `https://api.si.edu/openaccess/api/v1.0`)</li><li>`SMITHSONIAN_API_KEY` (required for live endpoint calls)</li></ul>\n<h2 id=\"security-requirements\">Security requirements</h2>\n<ul><li>Never commit/share `SMITHSONIAN_API_KEY`.</li><li>Never emit the key in logs or error responses.</li><li>Keep outbound calls server-side only (no client-exposed key).</li></ul>\n<h2 id=\"standards-mapping-tests\">Standards mapping + tests</h2>\n<p>Required rounds (minimum): object/provenance/shared-structure + protocol/search rounds.</p>\n<p>Required tests (failing-first):</p>\n<ul><li>`tests/adapters/smithsonian.test.ts`</li><li>`tests/api/smithsonian/profile.test.ts`</li><li>`tests/api/smithsonian/search.test.ts`</li><li>`tests/api/smithsonian/content.test.ts`</li><li>`tests/api/smithsonian/import.test.ts`</li></ul>\n<p>Protocol checks (B8):</p>\n<ul><li>OPTIONS/CORS behavior on new routes</li><li>response shape conformance</li><li>URI opacity + array-cardinality safety where applicable</li></ul>\n<h2 id=\"exit-criteria\">Exit criteria</h2>\n<ul><li>Adapter + routes + tests green.</li><li>`/explore` can search/import Smithsonian records.</li><li>PR includes Standards Mapping note with round + fixture anchor coverage.</li></ul>\n<h2 id=\"constraint-hardening-notes\">Constraint hardening notes</h2>\n<ul><li>`SMITHSONIAN_API_KEY` is required for search/content/import fetches to Smithsonian endpoints.</li><li>`/api/smithsonian/search` route-level schema validates official pagination fields:</li><li>`start` integer `&gt;= 0`</li><li>`rows` integer `1..1000`</li><li>Backward-compatible aliases (`offset`/`limit`) remain accepted for older internal callers, but `start`/`rows` are canonical.</li></ul>","updatedAt":"2018-10-20T01:46:40.000Z","checksum":"db1ffa4cab027620662f30f3298f9fc1de983ddbb7858a2071efe7e59afc410c","checksumPrefix":"db1ffa4cab02","anchorCount":12,"lineCount":98,"rawUrl":"/api/docs/content?path=providers%2Fsmithsonian-open-access.md","htmlUrl":"/docs?doc=providers%2Fsmithsonian-open-access.md","apiUrl":"/api/docs/content?path=providers%2Fsmithsonian-open-access.md"}