- Base URL
- oakmonttechnologies.com/api/v1
- Auth
- Bearer
- Format
- REST · JSON
- Quota
- By plan
Build on OAKMONT,in your own stack.
Call our platform programmatically - accessibility scans, price quotes, and more - in CI, in your CMS, or in your own product. REST, JSON, authenticated with an API key and metered per call.
Request
curl -X POST https://oakmonttechnologies.com/api/v1/scan \
-H "Authorization: Bearer oak_live_xxx" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.gov/about"}'Response
{
"id": "9f3c…",
"url": "https://example.gov/about",
"score": 82,
"grade": "B",
"totals": { "critical": 1, "serious": 2, "moderate": 1 },
"issues": [
{ "impact": "critical", "wcag": "1.1.1",
"title": "Images missing alt text (3)",
"help": "Every <img> needs an alt attribute…", "count": 3 }
]
}Authentication
Create a key under Portal → Developer API. Send it on every request:
Authorization: Bearer oak_live_xxxBase URL: https://oakmonttechnologies.com/api/v1
POST /scan - accessibility scan
Scan any public URL for common WCAG 2.1 AA / Section 508 failures.
curl -X POST https://oakmonttechnologies.com/api/v1/scan \
-H "Authorization: Bearer oak_live_xxx" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.gov/about"}'{
"id": "9f3c…",
"url": "https://example.gov/about",
"score": 82,
"grade": "B",
"totals": { "critical": 1, "serious": 2, "moderate": 1 },
"issues": [
{ "impact": "critical", "wcag": "1.1.1",
"title": "Images missing alt text (3)",
"help": "Every <img> needs an alt attribute…", "count": 3 }
]
}POST /quote - price a job
Get an itemized quote for a remediation job from the live rate card.
curl -X POST https://oakmonttechnologies.com/api/v1/quote \
-H "Authorization: Bearer oak_live_xxx" \
-H "Content-Type: application/json" \
-d '{"plan_key": "page_508", "chars": 12000}'The scanner family
The same engines behind the free tools, metered against your monthly quota: AI Act transparency, trackers and consent, email deliverability, and the Polish FA invoice structure check. Full request and response shapes live in the machine-readable index at GET /api/v1.
# AI Act transparency (Article 50)
curl -X POST https://oakmonttechnologies.com/api/v1/ai-scan -H "Authorization: Bearer oak_live_xxx" \
-H "Content-Type: application/json" -d '{"url": "https://example.com"}'
# Trackers and consent platform
curl -X POST https://oakmonttechnologies.com/api/v1/privacy-scan -H "Authorization: Bearer oak_live_xxx" \
-H "Content-Type: application/json" -d '{"url": "https://example.com"}'
# Deliverability: MX, SPF, DMARC, DKIM
curl -X POST https://oakmonttechnologies.com/api/v1/email-check -H "Authorization: Bearer oak_live_xxx" \
-H "Content-Type: application/json" -d '{"domain": "example.com"}'
# Polish FA invoice structure (KSeF)
curl -X POST https://oakmonttechnologies.com/api/v1/ksef-check -H "Authorization: Bearer oak_live_xxx" \
-H "Content-Type: application/json" -d '{"xml": "<Faktura>...</Faktura>"}'
# LLM regression grading (deterministic, no model runs)
curl -X POST https://oakmonttechnologies.com/api/v1/eval -H "Authorization: Bearer oak_live_xxx" \
-H "Content-Type: application/json" \
-d '{"cases": [{"key": "refund", "assertions": [{"kind": "contains", "value": "30 days"}]}], "answers": {"refund": "You have 30 days to return it."}}'POST /gate - The build gate
Your pipeline runs the checks, on branches and hosts nothing outside can reach, and posts what it found. This decides whether the build passes and says exactly why - including why each of the rules it did not fire on stayed quiet.
# The ruleset your build is held to, worst first by what we actually see
curl https://oakmonttechnologies.com/api/v1/rules/ci?level=AA -H "Authorization: Bearer oak_live_xxx"
# Your pipeline ran the checks; this decides the build and can sign the verdict
curl -X POST https://oakmonttechnologies.com/api/v1/gate -H "Authorization: Bearer oak_live_xxx" -H "Content-Type: application/json" -d '{"url": "https://staging.internal/checkout", "level": "AA", "fail_on": "serious",
"prove": true, "findings": [{"code": "input-no-label", "selector": "#cvc"}]}'{
"passed": false,
"level": "AA", "fail_on": "serious",
"failures": [
{ "code": "input-no-label", "criterion": "1.3.1", "impact": "critical",
"count": 1, "selectors": ["#cvc"] }
],
"advisories": [
{ "code": "heading-skip", "criterion": "1.3.1",
"advisory_because": "No criterion says heading levels may not skip." }
],
"digest": "3f9a…",
"proof": { "id": "…", "verify_url": "https://oakmonttechnologies.com/verify/…" }
}Two false failures and somebody adds continue-on-error, and after that a gate is decoration. So a criterion above the level you asked for, a criterion WCAG 2.2 withdrew, and anything a machine cannot honestly decide are reported and never block. Ask for prove and the verdict comes with a signed receipt naming the exact ruleset, so a green build cannot be re-read later against a ruleset that has since been tightened.
The notary
A dated, publicly checkable receipt over a hash you compute yourself, so the file never leaves your side. Priced per receipt rather than per call, because a receipt is the thing your customer keeps.
Errors
Failed calls use standard HTTP status codes and return a JSON body with a detail message.
| Status | Meaning |
|---|---|
| 400 | Invalid request body, for example a malformed URL or a missing field. |
| 401 | Missing, malformed, or revoked API key. |
| 404 | Referenced resource not found, for example an unknown plan_key on /quote. |
| 429 | Monthly API quota reached. See the Retry-After and X-RateLimit headers. |
{ "detail": "Invalid or revoked API key." }Limits
Calls are metered monthly per plan (Free 100 · Basic 5,000 · Pro 50,000). Exceeding your quota returns 429. Upgrade anytime from billing.
Every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset (a Unix timestamp for the start of next month). A 429 also returns Retry-After in seconds.
HTTP/1.1 200 OK
X-RateLimit-Limit: 5000
X-RateLimit-Remaining: 4987
X-RateLimit-Reset: 1751328000
# When the monthly quota is exhausted:
HTTP/1.1 429 Too Many Requests
Retry-After: 1209600
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0From JavaScript
Same two calls, without curl.
const res = await fetch("https://oakmonttechnologies.com/api/v1/scan", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.OAKMONT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({url: "https://example.gov/about"}),
});
if (!res.ok) throw new Error(`OAKMONT ${res.status}: ${await res.text()}`);
const {score, grade, issues} = await res.json();Machine-readable specification
The API describes itself. Point your generator at the OpenAPI document and get a typed client rather than hand-written fetch calls.
https://oakmonttechnologies.com/api/openapi.jsonThe document is generated from the running service, so it is never out of date with the endpoints it describes.
Embed the rate card
One line, no key, no build step. It reads the same catalogue /pricing reads, so a page carrying it cannot go out of date. data-ref carries your partner code through to every link; data-group narrows it to one family of plans.
<script src="https://oakmonttechnologies.com/embed/rate-card.js"
data-ref="your-partner-code"
data-group="managed_sub"></script>Or read it as JSON: https://oakmonttechnologies.com/api/public/rate-card
Full reference
Browse the full, machine-readable endpoint index at /api/v1.
