Score a spec via API
Paste a spec, get a grade. Elva’s scoring engine runs as a public HTTP API at https://api.getelva.ai so you can score any OpenAPI document straight from your terminal, with no account and no key.
GET /api/review/checks and POST /api/review are public scoring endpoints. Scoring uploads the submitted specification to Elva; remove secrets and data you do not want to submit. Workspace operations use authentication and permissions appropriate to the route.
List the check catalog
GET /api/review/checks returns the full set of checks the engine runs, so you can see exactly what your spec is graded against before you submit anything. Each entry carries an id, category, name, description, severity, and weight.
curl https://api.getelva.ai/api/review/checks
The response is a flat array. A single element looks like this:
{
"id": "design-http-methods",
"category": "Design",
"name": "HTTP Method Semantics",
"description": "Methods are used for what they mean: GET and HEAD declare no request body, DELETE does not require one, PUT/PATCH and resource-creating POSTs declare the payload they accept, and PUT/PATCH/DELETE on a single resource document 404.",
"severity": "medium",
"weight": 4
}
Score a spec
POST /api/review takes your OpenAPI document and hands back category scores, a full per-check breakdown, and an overall grade. You can send the spec two ways, and the engine handles both transparently.
The simplest path: stream a spec file straight from disk. The body is the raw file contents, whether that is YAML or JSON.
curl -X POST https://api.getelva.ai/api/review \
-H "Content-Type: text/plain" \
--data-binary @openapi.yaml
Already holding a parsed spec? Send it as a JSON body and the engine serializes and scores it the same way.
curl -X POST https://api.getelva.ai/api/review \
-H "Content-Type: application/json" \
--data-binary @openapi.json
What comes back
The response contains category scores with coverage, individual check results, and the overall result. Check scorable before treating overallScore as a grade. The following is an illustrative response excerpt; the checks array is shortened.
{
"scores": {
"Design": {
"percentage": 82,
"grade": "B",
"coverage": 1
},
"DeveloperExperience": {
"percentage": 74,
"grade": "B",
"coverage": 1
},
"AIReadiness": {
"percentage": 66,
"grade": "C",
"coverage": 1
},
"Security": {
"percentage": 90,
"grade": "A",
"coverage": 1
}
},
"checks": [
{
"category": "AIReadiness",
"id": "ai-op-ids",
"status": "Pass",
"score": 1,
"comments": "All evaluated operation identifiers meet the requirement.",
"weight": 6
}
],
"overallScore": 78,
"overallGrade": "B",
"scorable": true,
"operationCount": 12,
"rubricCoverage": 1
}
Category weights are Design 30, Developer Experience 30, AI Readiness 20, and Security 20. Grades use unrounded percentages: A ≥84, B ≥74, C ≥64, D ≥52, otherwise F. NotApplicable checks are excluded. A fractional check score overrides fallback credit of Pass=1, Partial=0.5, Fail=0. Categories below 70% coverage are N/A and excluded from the overall average.
Response fields
Field | Meaning |
scores | Results keyed by Design, DeveloperExperience, AIReadiness, and Security. |
scores.<category>.percentage | Rounded weighted percentage; 0 when the category cannot be graded. |
scores.<category>.grade | A, B, C, D, F, or N/A. |
scores.<category>.coverage | Share of the category rubric evaluated, from 0 to 1. |
checks[] | Check ID, category, status, comments, and weight; score and other finding details may also be present. |
checks[].status | Pass, Partial, Fail, or NotApplicable. |
checks[].score | Optional credit from 0 to 1, used instead of status fallback credit. |
overallScore / overallGrade | Weighted overall percentage and grade; inspect scorable before using them. |
scorable | Whether the available evidence supports an overall grade. |
unscorableReason | When unscorable: no-operations, unresolved-references, or insufficient-coverage. |
operationCount | Number of detected operations. |
rubricCoverage | Share of the full rubric evaluated, from 0 to 1. |
Error responses
The endpoint fails fast and tells you why. Both errors return a JSON body with a single error field.
Status | When it happens |
| The request body is missing or could not be read as a spec. |
| The body parsed, but it is not a valid OpenAPI document. |
The same rubric powers collection quality and AI Readiness findings. Resolve external references into a self-contained spec before submitting it. For CI, fail or request review when scorable is false; do not interpret N/A as a passing score.
Handle an unscorable report
{
"overallScore": 0,
"overallGrade": "N/A",
"scorable": false,
"unscorableReason": "no-operations",
"operationCount": 0,
"rubricCoverage": 0
}
Inspect the reason and the per-check comments. Add the missing operations, resolve references, or complete the specification enough to evaluate the rubric, then score it again. An HTTP success response means the review completed; it does not guarantee a usable grade.
On this page
- Score a spec via API