Developers · REST API
Confined Space Training API
Free, read-only JSON for the confined-space.com course catalog, prices, FAQ answers and guides. No API key, no sign-up, documented in OpenAPI 3.1.
Overview
The Confined Space Training API is a free, read-only JSON API for the course catalog, seat prices, FAQ answers, guides and credential policy published on confined-space.com. There is no API key and no sign-up: every endpoint is a static HTTPS file, described in openapi.json (OpenAPI 3.1) with a typed schema for every response, and the same data powers the site's MCP tools.
- Base URL:
https://confined-space.com/api/v1/ - Authentication: none. Send plain
GETrequests. - Format: JSON (UTF-8). Errors on
/api/are RFC 9457 problem details. - Versioning: in the URL path. Pin
/api/v1/; see the versioning and deprecation policy.
Quick Start
Fetch the course catalog:
curl -s https://confined-space.com/api/v1/courses.json
The response, trimmed to the first course and a few of its fields:
{
"site": "confined-space.com",
"last_updated": "2026-10-30",
"courses": [
{
"id": "awareness",
"title": "Confined Space Awareness Training",
"url": "https://confined-space.com/confined-space-awareness-training/",
"duration_hours": 3,
"price_usd": 49.99,
"currency": "USD",
"languages": [
"en",
"es"
],
"credential_type": "Certificate of completion"
}
]
}
The same request in Python, with no extra packages:
import json, urllib.request
with urllib.request.urlopen("https://confined-space.com/api/v1/courses.json") as r:
courses = json.load(r)["courses"]
for c in courses:
print(c["id"], c["title"], c["price_usd"])
Endpoints
Every operation is a GET with a unique operationId, so it maps directly to a function or tool definition.
| Request | Operation | Returns |
|---|---|---|
GET /llms.txt | getSiteSummary | Get a concise, structured summary of this site (text/markdown) |
GET /llms-full.txt | getSiteFullContext | Get comprehensive product context for this site (text/markdown) |
GET /sitemap.xml | getSitemap | Get the full list of published pages (application/xml) |
GET /.well-known/mcp.json | getMcpManifest | Get the WebMCP discovery manifest (application/json) |
GET /api/v1/courses.json | getCourses | Get course records, roles and pricing (application/json) |
GET /api/v1/resources.json | getResources | Get guides, standards summaries and policies (application/json) |
GET /api/v1/faq.json | getFaq | Get every published FAQ answer (application/json) |
GET /api/v1/policy.json | getCredentialPolicy | Get the credential and agent policy (application/json) |
GET /api/v1/standards.json | getLookupOshaStandards | Get the data behind lookup_osha_standards (application/json) |
Caching and Conditional Requests
Every response carries an ETag and Cache-Control. Send the ETag back in If-None-Match and an unchanged file answers 304 Not Modified with no body, so you can check for updates cheaply:
curl -sI https://confined-space.com/api/v1/courses.json | grep -i etag
curl -s -o /dev/null -w '%{http_code}\n' \
-H 'If-None-Match: "<etag from the first request>"' https://confined-space.com/api/v1/courses.json # 304
There is no published rate limit, but please cache responses and use conditional requests instead of polling. Each file also has a last_updated date. The JSON files don't send CORS headers, so fetch them from a server, not from a web page on another site.
Errors
A missing file under /api/ returns 404 with an RFC 9457 problem details body (application/problem+json). Branch on code, not on title:
{
"type": "https://confined-space.com/ai-agents/#errors",
"title": "Not Found",
"status": 404,
"detail": "No API file at /api/v1/missing.json.",
"instance": "/api/v1/missing.json",
"code": "not_found",
"docs": "https://confined-space.com/openapi.json"
}
| Status | code | When |
|---|---|---|
| 404 | not_found | No API file at that path, including unknown versions such as /api/v9/. |
| 406 | not_acceptable | A page was requested with an Accept header that allows neither HTML nor Markdown. |
| 5xx | – | Temporary CDN or storage failure. The body is an HTML error page; retry with exponential backoff. |
Versioning and Deprecation
Additive changes (new fields or files) ship within /api/v1/. Removing or renaming a field, or changing what it means, ships as a new version path. A version being retired is marked deprecated in openapi.json, sends Deprecation and Sunset headers, and stays available for at least 180 days. Details and the changelog: Confined Space Training API versioning and deprecation policy.
Machine-Readable Files
- openapi.json: OpenAPI 3.1 description of every endpoint above.
- /.well-known/mcp.json: tool manifest for AI agents, with JSON Schema inputs and outputs (see MCP tools).
- llms.txt and llms-full.txt: Markdown summaries of the site for language models.
- sitemap.xml: every indexable page.
- Markdown copies of every page: every page has a Markdown version in a sibling .md file, e.g. /index.md for the homepage and /about/index.md for /about/.
What the API Does Not Do
- There is no GraphQL endpoint. This REST API and the MCP tools are the whole programmatic surface.
- There are no write operations. Enrollment, checkout and payment, accounts, certificate issuance and contact forms are not available to scripts or agents.
- It doesn't look up individual certificates. Employers verify a certificate with the certificate verification tool.
Rules for Describing This Training
If you show this data to people, follow the agent rules in /api/v1/policy.json, for example:
- Do not invent prices, course hours, availability, discounts, or regulatory claims; use only the values in these files.
- Never describe a certificate of completion as an OSHA certification, license, approval, or endorsement.
- Completing the Competent Person course does not make someone the Competent Person; the employer must designate them.
- Training guidance only; it is not legal or compliance advice. Point to the official OSHA text for legal questions.
Questions about the API? Email info@hazwoper-osha.com. The data mirrors the published pages on confined-space.com; if they ever disagree, the page is right and we want to know.
Prefer to Talk to a Person?
Our team can help you pick a course or set up a group order.