Parsing Validation Responses
This page explains the structured error objects the public API returns, how severity differs between validate and submit, and how an agent should self-correct. For the full code list with anchors, see the Validation reference.
The Error Object Shape
Wherever the API reports a per-field problem — in a top-level errors array on an error envelope, or inside errors / warnings of a validate report — each entry has the same shape:
{
"field": "email",
"code": "format",
"message": "Value is not a valid email address.",
"help": "https://docs.kinoforms.com/developer/api/validation#format"
}field— the form fieldkeythe problem is about. May be absent for form-level problems.code— a stable machine code. Branch on this. The full set is in the Validation reference.message— a human-readable description. Show it to humans; do not parse it in code.help— a deep link to the documentation anchor for this exact code, e.g..../developer/api/validation#format. An agent can fetch this to learn the rule and the fix.
Where Errors Appear
| Endpoint | Result | Where problems show up |
|---|---|---|
validate | always 200 | data.errors, data.warnings, data.missingRequired |
submit | 200 on success, 422 on bad data | top-level errors array (with code: "validation_failed") |
submit?partial=true | 200 | top-level errors for malformed fields; data.missingRequired for gaps |
Severity: Validate vs Submit
The same problem can be a warning in one place and an error in another. This is intentional: validate is permissive so you can explore; submit is strict so bad data never lands.
| Situation | On validate | On submit |
|---|---|---|
| Missing required field | reported in missingRequired (still valid: false) | error → 422 validation_failed |
unknown_field (field not in schema) | warning (field ignored) | error → 422 validation_failed |
Malformed value (format, type_mismatch, pattern, …) | error in errors | error → 422 validation_failed |
In partial mode (submit?partial=true), missing required fields are downgraded to missingRequired (no error), but malformed values are still errors.
How an Agent Should Self-Correct
The reliable pattern is validate-loop, then submit once:
1. Build the best `data` you can.
2. POST /validate → read data.errors, data.warnings, data.missingRequired.
3. If errors or missingRequired is non-empty:
- For each error: look up code (or fetch `help`), fix the field's value.
- For each missingRequired key: supply a value.
- For each unknown_field warning: drop that key (submit would reject it).
- Go to step 2.
4. When valid === true and missingRequired is empty: POST /submit.
5. If submit still returns 422 (a race, or a rule only checked on write):
read the errors array, fix, and re-validate before retrying.Notes for robust agents:
- Branch on
code, never onmessage. Messages may change; codes are stable. - Resolve
unknown_fieldbefore submit. It is only a warning on validate, but it is a hard error on submit. Drop the offending key or map it to a real fieldkey. - Use
helpwhen you do not recognize a code. It points at the exact rule and how to fix it. - Respect rate limits. Validate is throttled generously for iteration; submit is 1 per 5 seconds per agent. Iterate on validate, not on submit.
- Treat
missingRequiredas a checklist. Keep validating until it is empty.
Worked Example
Validate response:
{
"data": {
"valid": false,
"errors": [
{ "field": "age", "code": "type_mismatch", "message": "Expected a number.",
"help": "https://docs.kinoforms.com/developer/api/validation#type_mismatch" }
],
"warnings": [
{ "field": "nickname", "code": "unknown_field", "message": "Field is not part of this form.",
"help": "https://docs.kinoforms.com/developer/api/validation#unknown_field" }
],
"missingRequired": ["email"]
},
"apiVersion": "v1"
}The agent should:
age→type_mismatch: coerce"42"to42.nickname→unknown_fieldwarning: remove thenicknamekey (submit would reject it).missingRequired: ["email"]: add a validemail.- Re-validate →
valid: true,missingRequired: []. submit.
