Interactions API: Granular Validation
Granular Validation support added to Interactions API
POST /interactions now validates each interaction in a request individually and returns a structured result describing exactly what happened to every record. Previously a single invalid interaction rejected the entire request; now the valid interactions in a batch are published even when others are rejected.
New status code semantics:
- 200 — every interaction was valid and published.
- 207 — some interactions were published and some were rejected.
- 400 — every interaction was rejected (returned as the same batch body), or the request itself was invalid (empty, or more than 100 interactions), which returns a plain error instead.
- Precise, per-record error fields. Each rejected error has a
fieldand anerrorMessage.
❗If anything other than a 200 is treated as a hard failure by the client they will need to update to handle the new 207 code.❗
Previous Response Examples
All interactions valid - 200 Echoed the request back.
{
"interactions": [
{
"interactionId": "3f2a9c7e-1b4d-4c8a-9e2f-6a7b8c9d0e1f",
"person": [{ "id": "80001", "type": "ngpvan" }],
"channel": { "type": "phone_number", "value": "+12025550176" },
"stateCode": "OH",
"attemptDateTime": "2026-07-27T08:00:00Z",
"method": "email",
"committee": [{ "id": "harbor-city-dems", "type": "committee_id" }],
"canvasser": [{ "id": "4400", "type": "canvasser_id" }],
"vendorSource": "CanvassKit",
"outcome": "successful_contact",
"jsonMetadata": "{\"seq\": 0, \"campaign\": \"fall-gotv\"}"
}
]
}Any interactions invalid - 400 Bad Request Any invalid interaction returned a 400 with a flat validation-error array.
[
{
"propertyName": "Interactions[3].StateCode",
"errorMessage": "State code must be a valid two-letter state code.",
"attemptedValue": "ca",
"customState": null,
"severity": "Error",
"errorCode": "RegularExpressionValidator",
"formattedMessagePlaceholderValues": {
"RegularExpression": "^[A-Z]{2}$",
"PropertyName": "State Code",
"PropertyValue": "ca",
"PropertyPath": "Interactions[3].StateCode",
"CollectionIndex": 3
}
},
{
"propertyName": "Interactions[7].Method",
"errorMessage": "'Method' must not be empty.",
"attemptedValue": "unknown",
"customState": null,
"severity": "Error",
"errorCode": "NotEmptyValidator",
"formattedMessagePlaceholderValues": {
"PropertyName": "Method",
"PropertyValue": "unknown",
"PropertyPath": "Interactions[7].Method",
"CollectionIndex": 7
}
},
{
"propertyName": "Interactions[7].Method",
"errorMessage": "'unknown' is not a valid interaction method.",
"attemptedValue": "unknown",
"customState": null,
"severity": "Error",
"errorCode": "NotEqualValidator",
"formattedMessagePlaceholderValues": {
"ComparisonValue": "unknown",
"ComparisonProperty": "",
"PropertyName": "Method",
"PropertyValue": "unknown",
"PropertyPath": "Interactions[7].Method",
"CollectionIndex": 7
}
}
]New Response Examples
All interactions valid — 200
{
"correlationId": "11534196688560234",
"totalInteractions": 1,
"acceptedInteractions": {
"count": 1,
"data": [
{
"interactionId": "3f2a9c7e-1b4d-4c8a-9e2f-6a7b8c9d0e1f",
"index": 0
}
]
},
"rejectedInteractions": { "count": 0, "data": [] }
}Some interactions rejected — 207
Two interactions were submitted; the one at index 1 was rejected (invalid state code). The interaction at index 0 was still published.
{
"correlationId": "11534196688560235",
"totalInteractions": 2,
"acceptedInteractions": {
"count": 1,
"data": [
{ "interactionId": "3f2a9c7e-1b4d-4c8a-9e2f-6a7b8c9d0e1f", "index": 0 }
]
},
"rejectedInteractions": {
"count": 1,
"data": [
{
"interactionId": "8d1e5f42-9a3b-4c17-8e6d-2f0a1b3c4d5e",
"index": 1,
"errors": [
{
"field": "stateCode",
"errorMessage": "State code must be a valid two-letter state code."
}
]
}
]
}
}All interactions rejected — 400
The same batch body is returned with an empty acceptedInteractions.data. Note the nested, indexed field path on the outcome-detail error.
{
"correlationId": "11534196688560236",
"totalInteractions": 1,
"acceptedInteractions": { "count": 0, "data": [] },
"rejectedInteractions": {
"count": 1,
"data": [
{
"interactionId": "8d1e5f42-9a3b-4c17-8e6d-2f0a1b3c4d5
e",
"index": 0,
"errors": [
{
"field": "outcomesDetailed[0].value.questionId",
"errorMessage": "'QuestionId' is required to be a
positive integer when VAN is included as a destination."
}
]
}
]
}
}See the API Examples and the API Reference for full details.

