- authentication
- Secret API key as a bearer token
- billing
- Free.
Tells Spaw what became of post your account sent to an address: delivered, returned (it came back), moved (the occupant is no longer there) or refused (delivery was refused). Your own reports feed your own later lookups of that address, with the dataset address-feedback: an address whose most recent report within 90 days is returned, moved or refused rather than delivered scores reported_returned (+50), and a delivery reported afterwards cancels it.
Reports also keep your postal suppression list: a moved or refused report suppresses the address at once, a second returned report with no later delivery suppresses it, and a delivered report clears an entry your reports added.
There is deliberately no cross-account reputation here and no provider webhook. A postal address is where somebody lives, and a shared "post fails here" database would be a database about residences. What you report raises the risk of your own lookups and of nobody else's, and no other account ever sees it.
Each item is a written address or the separated fields, and may name its own country, which wins over the request-level one. Addresses are folded the way a lookup folds them, so any spelling of one building lines up; an item that names no building — no postcode or locality, no street, no house number — is skipped and counted, not rejected. Feedback is free, never billed and never logged as a lookup. Reports are kept for 180 days.
Request body
| field | type | description |
|---|---|---|
| itemsrequired | object[] | 1 to 1,000 reports per request. |
| items[].address | string | null | The whole address written as it would be on an envelope. Required unless address_line1 is sent. At most 500 characters. |
| items[].address_line1 | string | null | The street line, when the address arrives separated. Required unless address is sent. At most 255 characters. |
| items[].address_line2 | string | null | At most 255 characters. |
| items[].organization | string | null | At most 200 characters. |
| items[].dependent_locality | string | null | At most 100 characters. |
| items[].locality | string | null | At most 100 characters. |
| items[].administrative_area | string | null | At most 100 characters. |
| items[].postal_code | string | null | At most 32 characters. |
| items[].po_box | string | null | At most 64 characters. |
| items[].country | string | null | This item's own country; overrides the request-level one. At most 2 characters. |
| items[].outcomerequired | string | One of: delivered, returned, moved, refused. |
| items[].occurred_at | string | null | When it happened. Defaults to now. |
| country | string | null | An ISO 3166-1 alpha-2 code applied to items that do not name their own. At most 2 characters. |
Example request
curl -X POST https://spaw.co/api/v1/address/feedback \
-H "Authorization: Bearer sk_live_…" \
-H "Content-Type: application/json" \
-d '{
"country": "GB",
"items": [
{
"address": "221B Baker Street, London NW1 6XE",
"outcome": "returned"
},
{
"address_line1": "10 Downing Street",
"locality": "London",
"postal_code": "SW1A 2AA",
"outcome": "moved",
"occurred_at": "2026-09-05T09:00:00Z"
}
]
}'Responses
202The reports were recorded.
{
"success": true,
"data": {
"recorded": 2,
"skipped": 0
}
}401The key is missing, malformed, or revoked.
{
"success": false,
"error": {
"code": "UNAUTHENTICATED",
"message": "Provide a valid API key as a bearer token.",
"request_id": "req_01m1kgdm4xngzmbmff68g94w0c"
}
}422The request body could not be validated; `error.errors` lists the fields.
{
"success": false,
"error": {
"code": "VALIDATION_FAILED",
"message": "The email field is required.",
"errors": {
"email": [
"The email field is required."
]
},
"request_id": "req_01m1kgdm4xngzmbmff68g94w0c"
}
}429Over 5 requests per second for the key. Retry after the limit resets.
{
"success": false,
"error": {
"code": "RATE_LIMITED",
"message": "Too many requests. Retry after the limit resets.",
"request_id": "req_01m1kgdm4xngzmbmff68g94w0c"
}
}Error codes
Failures answer { success: false, error: { code, message, request_id } }. Each code has its own page.