Evictions API
Menu

API reference

Every endpoint, with its request fields, its responses and a curl example. The sandbox runs the same API; serving and filing real cases are not available yet.

This page is generated from the API’s OpenAPI 3.1 document, which is also public at https://api.evictionsapi.com/v1/openapi.json. The examples use https://api.evictionsapi.com and placeholder keys.

What is available today. Evictions API is a sandbox beta, in test mode only. Available today: sign-up for a free sandbox account, the online case form, the REST API and a sandbox with a fictional test state, where a built-in sandbox reviewer reviews cases automatically, you can step them through to close and receive webhooks. Not available yet: serving notices or filing in court for a real case, in any state, live mode, which would accept real cases and online checkout.

Conventions

Authentication

Send your credential on every request except the public endpoints: Authorization: Bearer <key>. A missing or unknown credential is a 401; a credential of the wrong kind, such as an API key on an attorney endpoint, is a 403. Requests and responses are JSON; send Content-Type: application/json with a body.

Test and live keys

An API key has a mode, which is in its prefix: eak_test_ for test and eak_live_ for live. A case belongs to the mode of the key that created it, and a key sees only the cases of its own organization and mode: the same id with a key of the other mode is a 404.

Test mode uses sandbox adapters and the fictional state ZZ. Nothing is served or filed and nothing reaches a court. A live-mode case needs a state that is open, and no state is open yet, so a live-mode case cannot be served or filed. Use a test key: sign up for a sandbox account and create one under “API keys” in the app, or with POST /v1/api-keys.

Idempotency

Any POST that needs a credential accepts an Idempotency-Key header of 1 to 255 characters. The first request with a key is processed and its response is stored, for a 2xx or a 4xx answer (a 5xx answer is not stored, so retry it with the same key). Send the same request with the same key, from the same credential and in the same mode, and you get the stored response again, with the same status and an Idempotent-Replayed: true header, and nothing is processed twice.

Reuse a key with a different method, path, body or credential, or in the other mode, and the answer is 409 idempotency_conflict. Keys are scoped to your organization. The public endpoints ignore the header, and so do the endpoints that return a one-time secret (POST /v1/api-keys and POST /v1/webhook-endpoints): they run on every request and nothing is stored, so a secret is never kept for replay.

Create a case that is safe to retry
curl -X POST https://api.evictionsapi.com/v1/cases \
  -H "Authorization: Bearer eak_test_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: create-case-pat-landlord-2026-10" \
  -d '{ ... }'

Errors

Every error has the same shape, { "error": { "code", "message", "details" } }, and an HTTP status. Branch on code, which is stable; message is for people and can change. details is null unless the code says otherwise.

An invalid request
{
  "error": {
    "code": "invalid_request",
    "message": "The request is invalid.",
    "details": {
      "issues": [
        { "path": "contentBase64", "code": "invalid_format", "message": "must be valid base64" }
      ]
    }
  }
}
A case that does not exist
{ "error": { "code": "not_found", "message": "Case not found", "details": null } }
NameTypeRequiredDescription
errorobjectYes—
error.codestringYes—
error.messagestringYes—
error.detailsanyYes—
CodeStatusWhen
invalid_request400, 422The request body, query or Idempotency-Key is invalid (400; details.issues lists each problem), or a draft change is not allowed, such as changing ground or entryPoint (422; details.field names it).
unauthenticated401The Authorization header is missing, malformed or names an unknown or revoked credential.
forbidden403The credential is valid but not allowed here, for example an attorney endpoint called with an API key.
live_unavailable403Live mode is not available yet: a live API key or a signed-in session asking for live mode tried to create an API key, or a session sent X-Evictions-Mode: live.
attorney_not_eligible403Attorney endpoints only: the assigned attorney is not verified or not licensed in the property’s state.
not_found404The case, document, API key or webhook endpoint does not exist for your organization and mode, or the route does not exist.
invalid_state409The case is no longer a draft, so its facts cannot change and evidence cannot be added.
invalid_transition409The action is not allowed in the case’s current state, for example submitting a case that is not a draft.
guard_failed409A step needs something that is missing, such as a current attorney approval of the exact documents.
stale_approval409Attorney endpoints only: the approved document hashes do not match the current documents.
key_limit409POST /v1/api-keys only: the organization already has 10 active API keys in this mode. Revoke one first.
cannot_revoke_current_key409DELETE /v1/api-keys/{id} only: an API key tried to revoke itself. Use another key, or sign in.
sandbox_only409POST /v1/cases/{id}/advance only: the case is not a test-mode case in the sandbox jurisdiction. Live cases are never advanced.
nothing_to_advance409POST /v1/cases/{id}/advance only: the test case is a draft, on hold or finished, or is not waiting on anything the sandbox can move on.
idempotency_conflict409The Idempotency-Key was already used with a different request or credential.
payload_too_large413A document is over 10 MB after decoding, or the request body is too large.
unsupported_media_type415The request body is sent with a content type the API does not accept.
gates_failed422Submit only: the case did not pass the submission checks. details holds the check results.
prior_notice_missing422A prior-notice document was uploaded before the case recorded priorNotice.
documents_unavailable422Submit only: the jurisdiction has no documents for this ground and entry point.
rate_limited429Too many requests: more than 5 to POST /v1/public/leads from one address in 10 minutes, more than 10 sign-ups and sign-ins from one address in 10 minutes, or more than 60 sandbox advances per organization in a minute. Retry-After gives the seconds to wait.
busy503POST /v1/auth/signup and POST /v1/auth/login only: too many password checks are waiting. Nothing was created or changed. Retry-After: 5 gives the seconds to wait.
internal500An unexpected error. The response carries no detail.

Pagination

GET /v1/cases returns cases newest first, a page at a time. limit is the page size: 1 to 100, with a default 20; a larger number is treated as 100, and zero or anything that is not a positive whole number is a 400. Pass the nextCursor of one page as cursor to get the next. nextCursor is null on the last page. The cursor is opaque: do not build one. The events list and the attorney queue return everything and take no cursor.

A page of cases
{
  "items": [ { "id": "case_...", "state": "notice_review", ... } ],
  "nextCursor": "eyJ..."
}

Document upload

POST /v1/cases/{id}/documents takes JSON, not a multipart form: filename (1 to 255 characters, no path separators or control characters), purpose (one of authority, prior_notice, prior_notice_proof or other) and contentBase64, the file as standard base64 with padding. A file over 10 MB after decoding is a 413 payload_too_large; text that is not valid base64 is a 400.

Evidence can be added only while the case is a draft (otherwise 409 invalid_state), and a prior-notice document only after the case records priorNotice (422 prior_notice_missing). The response includes the document’s contentHash, the SHA-256 of its bytes. Documents of a case are downloaded with GET /v1/cases/{id}/documents/{docId}.

Customer endpoints

Called with an organization API key (or, from the website, a signed-in session). Everything you need to create, check, submit and follow a case.

GET /v1/jurisdictions/resolve

Whether a jurisdiction is served, and its notice rules

Authentication: API key, as Authorization: Bearer eak_test_...

Parameters

NameInTypeRequiredDescription
statequerystringYesTwo-letter state code. In test mode, ZZ is the fictional sandbox state.
countyquerystringNoCounty name, to include county-level rules.
cityquerystringNoCity name, to include city-level rules.

Responses

StatusMeaningBody
200Served status, jurisdiction ids and, when served in the key's mode, the rules for each ground.object
400The request is invalid.Error
401The credential is missing or invalid.Error
403The credential is not allowed to do this.Error
404Not found.Error
409The request conflicts with the current state: for a case, it is not in a state that allows this; for an API key, a limit or the key in use.Error
422The case did not pass a check.Error

Example

curl example for GET /v1/jurisdictions/resolve
curl "https://api.evictionsapi.com/v1/jurisdictions/resolve?state=ZZ" \
  -H "Authorization: Bearer eak_test_..."

POST /v1/cases

Create a draft case

Authentication: API key, as Authorization: Bearer eak_test_...

Request body

JSON. Fields not listed are rejected.

NameTypeRequiredDescription
groundstringYesOne of: "nonpayment", "lease_violation", "holdover".
entryPointstringYesOne of: "notice", "filing".
propertyobjectYes—
property.line1stringYes1 to 200 characters.
property.unitstringNo1 to 50 characters.
property.citystringYes1 to 100 characters.
property.countystringNo1 to 100 characters.
property.statestringYesPattern ^[A-Za-z]{2}$.
property.zipstringYesPattern ^\d{5}(-\d{4})?$.
property.ownerOfRecordstringYes1 to 200 characters.
partiesarray of objectYesUp to 20 items.
parties[].rolestringYesOne of: "plaintiff", "defendant".
parties[].namestringYes1 to 200 characters.
parties[].isEntitybooleanNo—
leaseobjectNo—
lease.startDatestringNo—
lease.endDatestringNo—
lease.monthlyRentCentsintegerNo0 or more.
ledgerarray of objectNoUp to 1000 items.
ledger[].datestringIf ledger is sent—
ledger[].typestringIf ledger is sentOne of: "charge", "payment".
ledger[].amountCentsintegerIf ledger is sent0 or more.
ledger[].memostringNo1 to 500 characters.
amountOwedCentsintegerNo0 or more.
violationobjectNo—
violation.descriptionstringIf violation is sent1 to 5000 characters.
violation.datestringIf violation is sent—
attestationsobjectYes—
attestations.authoritybooleanNo—
attestations.notRetaliatorybooleanNo—
attestations.notDiscriminatorybooleanNo—
attestations.servicememberstringNoOne of: "no", "yes", "unknown".
attestations.caresCoveredbooleanNo—
attestations.subsidizedbooleanNo—
priorNoticeobjectNo—
priorNotice.servedDatestringIf priorNotice is sent—
priorNotice.methodstringIf priorNotice is sentOne of: "personal", "substitute", "posting", "certified_mail", "first_class_mail".
priorNotice.periodDaysintegerIf priorNotice is sent1 to 365.
freeTextstringNoUp to 5000 characters.

Responses

StatusMeaningBody
201The draft case.Case
400The request is invalid.Error
401The credential is missing or invalid.Error
403The credential is not allowed to do this.Error
404Not found.Error
409The request conflicts with the current state: for a case, it is not in a state that allows this; for an API key, a limit or the key in use.Error
422The case did not pass a check.Error

Example

curl example for POST /v1/cases
curl -X POST https://api.evictionsapi.com/v1/cases \
  -H "Authorization: Bearer eak_test_..." \
  -H "Content-Type: application/json" \
  -d '{
  "ground": "nonpayment",
  "entryPoint": "notice",
  "property": {
    "line1": "1 Main St",
    "city": "Testville",
    "state": "ZZ",
    "zip": "00000",
    "ownerOfRecord": "Pat Landlord"
  },
  "parties": [
    { "role": "plaintiff", "name": "Pat Landlord" },
    { "role": "defendant", "name": "Terry Tenant" }
  ],
  "lease": { "startDate": "2025-01-01", "monthlyRentCents": 150000 },
  "ledger": [
    { "date": "2026-09-01", "type": "charge", "amountCents": 150000 },
    { "date": "2026-10-01", "type": "charge", "amountCents": 150000 },
    { "date": "2026-10-02", "type": "payment", "amountCents": 50000 }
  ],
  "amountOwedCents": 250000,
  "attestations": {
    "authority": true,
    "notRetaliatory": true,
    "notDiscriminatory": true,
    "servicemember": "no",
    "caresCovered": false
  }
}'

GET /v1/cases

List the cases of the key's organization and mode

Authentication: API key, as Authorization: Bearer eak_test_...

Parameters

NameInTypeRequiredDescription
cursorquerystringNoThe nextCursor of the previous page. Omit it for the first page.
limitquerystringNoPage size, 1 to 100. Default 20; a larger value is treated as 100.

Responses

StatusMeaningBody
200A page of cases, newest first.{ items: Case[], nextCursor: string | null }
400The request is invalid.Error
401The credential is missing or invalid.Error
403The credential is not allowed to do this.Error
404Not found.Error
409The request conflicts with the current state: for a case, it is not in a state that allows this; for an API key, a limit or the key in use.Error
422The case did not pass a check.Error

Example

curl example for GET /v1/cases
curl "https://api.evictionsapi.com/v1/cases?limit=20" \
  -H "Authorization: Bearer eak_test_..."

GET /v1/cases/{id}

Get a case

Authentication: API key, as Authorization: Bearer eak_test_...

Parameters

NameInTypeRequiredDescription
idpathstringYesThe case id.

Responses

StatusMeaningBody
200The case.Case
400The request is invalid.Error
401The credential is missing or invalid.Error
403The credential is not allowed to do this.Error
404Not found.Error
409The request conflicts with the current state: for a case, it is not in a state that allows this; for an API key, a limit or the key in use.Error
422The case did not pass a check.Error

Example

curl example for GET /v1/cases/{id}
curl https://api.evictionsapi.com/v1/cases/case_... \
  -H "Authorization: Bearer eak_test_..."

PATCH /v1/cases/{id}

Change the facts of a draft case

Authentication: API key, as Authorization: Bearer eak_test_...

Parameters

NameInTypeRequiredDescription
idpathstringYesThe case id.

Request body

JSON. Fields not listed are rejected.

NameTypeRequiredDescription
groundstringNoOne of: "nonpayment", "lease_violation", "holdover".
entryPointstringNoOne of: "notice", "filing".
propertyobjectNo—
property.line1stringIf property is sent1 to 200 characters.
property.unitstringNo1 to 50 characters.
property.citystringIf property is sent1 to 100 characters.
property.countystringNo1 to 100 characters.
property.statestringIf property is sentPattern ^[A-Za-z]{2}$.
property.zipstringIf property is sentPattern ^\d{5}(-\d{4})?$.
property.ownerOfRecordstringIf property is sent1 to 200 characters.
partiesarray of objectNoUp to 20 items.
parties[].rolestringIf parties is sentOne of: "plaintiff", "defendant".
parties[].namestringIf parties is sent1 to 200 characters.
parties[].isEntitybooleanNo—
leaseobjectNo—
lease.startDatestringNo—
lease.endDatestringNo—
lease.monthlyRentCentsintegerNo0 or more.
ledgerarray of objectNoUp to 1000 items.
ledger[].datestringIf ledger is sent—
ledger[].typestringIf ledger is sentOne of: "charge", "payment".
ledger[].amountCentsintegerIf ledger is sent0 or more.
ledger[].memostringNo1 to 500 characters.
amountOwedCentsintegerNo0 or more.
violationobjectNo—
violation.descriptionstringIf violation is sent1 to 5000 characters.
violation.datestringIf violation is sent—
attestationsobjectNo—
attestations.authoritybooleanNo—
attestations.notRetaliatorybooleanNo—
attestations.notDiscriminatorybooleanNo—
attestations.servicememberstringNoOne of: "no", "yes", "unknown".
attestations.caresCoveredbooleanNo—
attestations.subsidizedbooleanNo—
priorNoticeobjectNo—
priorNotice.servedDatestringIf priorNotice is sent—
priorNotice.methodstringIf priorNotice is sentOne of: "personal", "substitute", "posting", "certified_mail", "first_class_mail".
priorNotice.periodDaysintegerIf priorNotice is sent1 to 365.
freeTextstringNoUp to 5000 characters.

Responses

StatusMeaningBody
200The updated case.Case
400The request is invalid.Error
401The credential is missing or invalid.Error
403The credential is not allowed to do this.Error
404Not found.Error
409The request conflicts with the current state: for a case, it is not in a state that allows this; for an API key, a limit or the key in use.Error
422The case did not pass a check.Error

Example

curl example for PATCH /v1/cases/{id}
curl -X PATCH https://api.evictionsapi.com/v1/cases/case_... \
  -H "Authorization: Bearer eak_test_..." \
  -H "Content-Type: application/json" \
  -d '{ "amountOwedCents": 250000 }'

POST /v1/cases/{id}/documents

Upload evidence for a draft case

Authentication: API key, as Authorization: Bearer eak_test_...

Parameters

NameInTypeRequiredDescription
idpathstringYesThe case id.

Request body

JSON. Fields not listed are rejected.

NameTypeRequiredDescription
filenamestringYes1 to 255 characters.
purposestringYesOne of: "authority", "prior_notice", "prior_notice_proof", "other".
contentBase64stringYesAt least 1 characters.

Responses

StatusMeaningBody
201The stored document.Document
400The request is invalid.Error
401The credential is missing or invalid.Error
403The credential is not allowed to do this.Error
404Not found.Error
409The request conflicts with the current state: for a case, it is not in a state that allows this; for an API key, a limit or the key in use.Error
422The case did not pass a check.Error

Example

curl example for POST /v1/cases/{id}/documents
curl -X POST https://api.evictionsapi.com/v1/cases/case_.../documents \
  -H "Authorization: Bearer eak_test_..." \
  -H "Content-Type: application/json" \
  -d '{
  "filename": "deed.pdf",
  "purpose": "authority",
  "contentBase64": "ZGVlZA=="
}'

GET /v1/cases/{id}/documents/{docId}

Download a document of the case

Authentication: API key, as Authorization: Bearer eak_test_...

Parameters

NameInTypeRequiredDescription
idpathstringYesThe case id.
docIdpathstringYesThe document id.

Responses

StatusMeaningBody
200The document bytes.binaryapplication/pdf
400The request is invalid.Error
401The credential is missing or invalid.Error
403The credential is not allowed to do this.Error
404Not found.Error
409The request conflicts with the current state: for a case, it is not in a state that allows this; for an API key, a limit or the key in use.Error
422The case did not pass a check.Error

Example

curl example for GET /v1/cases/{id}/documents/{docId}
curl https://api.evictionsapi.com/v1/cases/case_.../documents/doc_... \
  -H "Authorization: Bearer eak_test_..." \
  -o document.pdf

POST /v1/cases/{id}/validate

Run the submission gates on a draft

Authentication: API key, as Authorization: Bearer eak_test_...

Parameters

NameInTypeRequiredDescription
idpathstringYesThe case id.

Responses

StatusMeaningBody
200The gate results.GateResults
400The request is invalid.Error
401The credential is missing or invalid.Error
403The credential is not allowed to do this.Error
404Not found.Error
409The request conflicts with the current state: for a case, it is not in a state that allows this; for an API key, a limit or the key in use.Error
422The case did not pass a check.Error

Example

curl example for POST /v1/cases/{id}/validate
curl -X POST https://api.evictionsapi.com/v1/cases/case_.../validate \
  -H "Authorization: Bearer eak_test_..."

POST /v1/cases/{id}/submit

Submit a draft that passes every gate for attorney review

Authentication: API key, as Authorization: Bearer eak_test_...

Parameters

NameInTypeRequiredDescription
idpathstringYesThe case id.

Responses

StatusMeaningBody
200The case, now in attorney review, and the gate results.{ case: Case, gates: object[] }
400The request is invalid.Error
401The credential is missing or invalid.Error
403The credential is not allowed to do this.Error
404Not found.Error
409The request conflicts with the current state: for a case, it is not in a state that allows this; for an API key, a limit or the key in use.Error
422The case did not pass a check.Error

Example

curl example for POST /v1/cases/{id}/submit
curl -X POST https://api.evictionsapi.com/v1/cases/case_.../submit \
  -H "Authorization: Bearer eak_test_..."

GET /v1/cases/{id}/events

Customer-visible events of the case, oldest first

Authentication: API key, as Authorization: Bearer eak_test_...

Parameters

NameInTypeRequiredDescription
idpathstringYesThe case id.

Responses

StatusMeaningBody
200The events.{ items: Event[] }
400The request is invalid.Error
401The credential is missing or invalid.Error
403The credential is not allowed to do this.Error
404Not found.Error
409The request conflicts with the current state: for a case, it is not in a state that allows this; for an API key, a limit or the key in use.Error
422The case did not pass a check.Error

Example

curl example for GET /v1/cases/{id}/events
curl https://api.evictionsapi.com/v1/cases/case_.../events \
  -H "Authorization: Bearer eak_test_..."

POST /v1/cases/{id}/report-cure

Report that the tenant has paid or cured

Authentication: API key, as Authorization: Bearer eak_test_...

Parameters

NameInTypeRequiredDescription
idpathstringYesThe case id.

Responses

StatusMeaningBody
200The case.Case
400The request is invalid.Error
401The credential is missing or invalid.Error
403The credential is not allowed to do this.Error
404Not found.Error
409The request conflicts with the current state: for a case, it is not in a state that allows this; for an API key, a limit or the key in use.Error
422The case did not pass a check.Error

Example

curl example for POST /v1/cases/{id}/report-cure
curl -X POST https://api.evictionsapi.com/v1/cases/case_.../report-cure \
  -H "Authorization: Bearer eak_test_..."

POST /v1/cases/{id}/withdraw

Withdraw the case

Authentication: API key, as Authorization: Bearer eak_test_...

Parameters

NameInTypeRequiredDescription
idpathstringYesThe case id.

Responses

StatusMeaningBody
200The withdrawn case.Case
400The request is invalid.Error
401The credential is missing or invalid.Error
403The credential is not allowed to do this.Error
404Not found.Error
409The request conflicts with the current state: for a case, it is not in a state that allows this; for an API key, a limit or the key in use.Error
422The case did not pass a check.Error

Example

curl example for POST /v1/cases/{id}/withdraw
curl -X POST https://api.evictionsapi.com/v1/cases/case_.../withdraw \
  -H "Authorization: Bearer eak_test_..."

POST /v1/cases/{id}/advance

Sandbox only: move a test case on by one step. Runs the step the case is waiting for now (the sandbox reviewer's review, a service or filing update, or the end of the notice period on the case's own sandbox clock), or records the next court outcome as the sandbox reviewer. A live case, or a case outside the sandbox jurisdiction, gets 409 `sandbox_only`; a draft, a case on hold or a finished case gets 409 `nothing_to_advance`, as does a step whose last try failed, until its automatic retry (`error.details.retryAt`). While the step is already being taken, the case is returned as it is. At most 60 a minute per organization (429 `rate_limited`)

Authentication: API key, as Authorization: Bearer eak_test_...

Parameters

NameInTypeRequiredDescription
idpathstringYesThe case id.

Responses

StatusMeaningBody
200The case after the step.Case
400The request is invalid.Error
401The credential is missing or invalid.Error
403The credential is not allowed to do this.Error
404Not found.Error
409The request conflicts with the current state: for a case, it is not in a state that allows this; for an API key, a limit or the key in use.Error
422The case did not pass a check.Error

Example

curl example for POST /v1/cases/{id}/advance
curl -X POST https://api.evictionsapi.com/v1/cases/case_.../advance \
  -H "Authorization: Bearer eak_test_..."

POST /v1/webhook-endpoints

Register a webhook endpoint

Authentication: API key, as Authorization: Bearer eak_test_...

Request body

JSON. Fields not listed are rejected.

NameTypeRequiredDescription
urlstringYes1 to 2048 characters.

Responses

StatusMeaningBody
201The endpoint. The signing secret appears in this response only. An `Idempotency-Key` header is ignored: every request creates an endpoint, and no response is stored or replayed.object
400The request is invalid.Error
401The credential is missing or invalid.Error
403The credential is not allowed to do this.Error
404Not found.Error
409The request conflicts with the current state: for a case, it is not in a state that allows this; for an API key, a limit or the key in use.Error
422The case did not pass a check.Error

Example

curl example for POST /v1/webhook-endpoints
curl -X POST https://api.evictionsapi.com/v1/webhook-endpoints \
  -H "Authorization: Bearer eak_test_..." \
  -H "Content-Type: application/json" \
  -d '{ "url": "https://example.com/webhooks/evictions" }'

GET /v1/webhook-endpoints

List the organization's webhook endpoints in the credential's mode. The signing secret is never shown again

Authentication: API key, as Authorization: Bearer eak_test_...

Responses

StatusMeaningBody
200The endpoints, oldest first.{ items: object[] }
400The request is invalid.Error
401The credential is missing or invalid.Error
403The credential is not allowed to do this.Error
404Not found.Error
409The request conflicts with the current state: for a case, it is not in a state that allows this; for an API key, a limit or the key in use.Error
422The case did not pass a check.Error

Example

curl example for GET /v1/webhook-endpoints
curl https://api.evictionsapi.com/v1/webhook-endpoints \
  -H "Authorization: Bearer eak_test_..."

GET /v1/api-keys

List the organization's API keys in the credential's mode, newest first, revoked ones included. The secret is never shown again

Authentication: API key, as Authorization: Bearer eak_test_...

Responses

StatusMeaningBody
200The keys, each with the last four characters of its secret (null for a key created before they were recorded) and when it was revoked, if it was.{ items: object[] }
400The request is invalid.Error
401The credential is missing or invalid.Error
403The credential is not allowed to do this.Error
404Not found.Error
409The request conflicts with the current state: for a case, it is not in a state that allows this; for an API key, a limit or the key in use.Error
422The case did not pass a check.Error

Example

curl example for GET /v1/api-keys
curl https://api.evictionsapi.com/v1/api-keys \
  -H "Authorization: Bearer eak_test_..."

POST /v1/api-keys

Create a test-mode API key. Live keys cannot be created yet (403 `live_unavailable`); at most 10 active keys per mode (409 `key_limit`)

Authentication: API key, as Authorization: Bearer eak_test_...

Responses

StatusMeaningBody
201The new key. The secret appears in this response only. An `Idempotency-Key` header is ignored: every request creates a key, and no response is stored or replayed.{ id: string, mode: string, secret: string }
400The request is invalid.Error
401The credential is missing or invalid.Error
403The credential is not allowed to do this.Error
404Not found.Error
409The request conflicts with the current state: for a case, it is not in a state that allows this; for an API key, a limit or the key in use.Error
422The case did not pass a check.Error

Example

curl example for POST /v1/api-keys
curl -X POST https://api.evictionsapi.com/v1/api-keys \
  -H "Authorization: Bearer eak_test_..."

DELETE /v1/api-keys/{id}

Revoke an API key of the organization and the credential's mode. A key cannot revoke itself (409 `cannot_revoke_current_key`)

Authentication: API key, as Authorization: Bearer eak_test_...

Parameters

NameInTypeRequiredDescription
idpathstringYesThe API key id.

Responses

StatusMeaningBody
204The key is revoked and no longer authenticates. Revoking a revoked key is also 204.—
400The request is invalid.Error
401The credential is missing or invalid.Error
403The credential is not allowed to do this.Error
404Not found.Error
409The request conflicts with the current state: for a case, it is not in a state that allows this; for an API key, a limit or the key in use.Error
422The case did not pass a check.Error

Example

curl example for DELETE /v1/api-keys/{id}
curl -X DELETE https://api.evictionsapi.com/v1/api-keys/key_... \
  -H "Authorization: Bearer eak_test_..."

DELETE /v1/webhook-endpoints/{id}

Delete a webhook endpoint. Deliveries still waiting to be retried for it are dropped

Authentication: API key, as Authorization: Bearer eak_test_...

Parameters

NameInTypeRequiredDescription
idpathstringYesThe webhook endpoint id.

Responses

StatusMeaningBody
204The endpoint and its delivery log are deleted.—
400The request is invalid.Error
401The credential is missing or invalid.Error
403The credential is not allowed to do this.Error
404Not found.Error
409The request conflicts with the current state: for a case, it is not in a state that allows this; for an API key, a limit or the key in use.Error
422The case did not pass a check.Error

Example

curl example for DELETE /v1/webhook-endpoints/{id}
curl -X DELETE https://api.evictionsapi.com/v1/webhook-endpoints/whe_... \
  -H "Authorization: Bearer eak_test_..."

GET /v1/organization

The caller's organization and its members

Authentication: API key, as Authorization: Bearer eak_test_...

Responses

StatusMeaningBody
200The organization and its members.{ id: string, name: string, verified: boolean, members: object[] }
400The request is invalid.Error
401The credential is missing or invalid.Error
403The credential is not allowed to do this.Error
404Not found.Error
409The request conflicts with the current state: for a case, it is not in a state that allows this; for an API key, a limit or the key in use.Error
422The case did not pass a check.Error

Example

curl example for GET /v1/organization
curl https://api.evictionsapi.com/v1/organization \
  -H "Authorization: Bearer eak_test_..."

PATCH /v1/organization

Rename the organization. Only an owner, signed in with a session; an API key or a plain member gets 403

Authentication: Session token, as Authorization: Bearer ess_...

Request body

JSON. Fields not listed are rejected.

NameTypeRequiredDescription
namestringYes1 to 120 characters.

Responses

StatusMeaningBody
200The organization after the change.{ id: string, name: string, verified: boolean, members: object[] }
400The request is invalid.Error
401The credential is missing or invalid.Error
403The credential is not allowed to do this.Error
404Not found.Error
409The request conflicts with the current state: for a case, it is not in a state that allows this; for an API key, a limit or the key in use.Error
422The case did not pass a check.Error

Example

curl example for PATCH /v1/organization
curl -X PATCH https://api.evictionsapi.com/v1/organization \
  -H "Authorization: Bearer ess_..." \
  -H "Content-Type: application/json" \
  -d '{ "name": "Acme Property Management" }'

POST /v1/auth/logout

Revoke the session in use

Authentication: Session token, as Authorization: Bearer ess_...

Responses

StatusMeaningBody
204The session is revoked.—
400The request is invalid.Error
401The credential is missing or invalid.Error
403The credential is not allowed to do this.Error
404Not found.Error
409The request conflicts with the current state: for a case, it is not in a state that allows this; for an API key, a limit or the key in use.Error
422The case did not pass a check.Error

Example

curl example for POST /v1/auth/logout
curl -X POST https://api.evictionsapi.com/v1/auth/logout \
  -H "Authorization: Bearer ess_..."

GET /v1/me

The signed-in user, their organization and the modes available to it

Authentication: Session token, as Authorization: Bearer ess_...

Responses

StatusMeaningBody
200The user, the organization and the modes. Live mode is not available yet.{ user: object, organization: object, modes: object }
400The request is invalid.Error
401The credential is missing or invalid.Error
403The credential is not allowed to do this.Error
404Not found.Error
409The request conflicts with the current state: for a case, it is not in a state that allows this; for an API key, a limit or the key in use.Error
422The case did not pass a check.Error

Example

curl example for GET /v1/me
curl https://api.evictionsapi.com/v1/me \
  -H "Authorization: Bearer ess_..."

Response objects

The objects the customer endpoints return. Response shapes are described by hand in the OpenAPI document and are deliberately loose.

Case

NameTypeRequiredDescription
idstringYes—
modestringYesOne of: "test", "live".
statestringYesPosition in the case lifecycle, for example `notice_review` or `filing_submitted`.
heldFromstring | nullNo—
groundstringYes—
entryPointstringYesOne of: "notice", "filing".
courtCaseNumberstring | nullNo—
packVersionsobject | nullNo—
dataobjectYes—
deadlinesarray of objectYes—
deadlines[].namestringYes—
deadlines[].datestringYesFormat: date.
deadlines[].citationstringYes—
documentsarray of DocumentYes—
nextActionobjectYes—
nextAction.bystringYesOne of: "customer", "attorney", "platform", "court", "none".
nextAction.descriptionstringYes—
createdAtstringNoFormat: date-time.
updatedAtstringNoFormat: date-time.

Document

NameTypeRequiredDescription
idstringYes—
kindstringYesOne of: "evidence", "notice", "filing", "proof".
specIdstring | nullNo—
filenamestringYes—
contentHashstringYesSHA-256 of the document bytes. An attorney approval names these.
createdAtstringNoFormat: date-time.

GateResults

NameTypeRequiredDescription
passedbooleanYes—
resultsarray of objectYes—
results[].gatestringYes—
results[].statusstringYes—
results[].reasonstringNo—

Event

NameTypeRequiredDescription
idstringYes—
actionstringYes—
actorTypestringYes—
fromStatestring | nullYes—
toStatestring | nullYes—
detailanyNo—
createdAtstringYesFormat: date-time.

Public endpoints

No credential. Health, the OpenAPI document, the endpoint behind the website’s forms, and account sign-up and sign-in.

GET /v1/health

Liveness check

Authentication: none

Responses

StatusMeaningBody
200The service is up.{ ok: boolean }

Example

curl example for GET /v1/health
curl https://api.evictionsapi.com/v1/health

GET /v1/openapi.json

This OpenAPI document

Authentication: none

Responses

StatusMeaningBody
200The OpenAPI 3.1 document.object

Example

curl example for GET /v1/openapi.json
curl https://api.evictionsapi.com/v1/openapi.json

POST /v1/auth/signup

Create an account: an unverified customer organization, its owner and a session. No credential; the website calls this from its servers

Authentication: none

Request body

JSON. Fields not listed are rejected.

NameTypeRequiredDescription
namestringYes1 to 120 characters.
organizationNamestringYes1 to 120 characters.
emailstringYesFormat: email. Up to 254 characters. Pattern ^(?:[A-Za-z0-9_'+\-]+\.)*[A-Za-z0-9_'+\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$.
passwordstringYes10 to 200 characters.

Responses

StatusMeaningBody
201The new session, user and organization. An `Idempotency-Key` header is ignored.{ token: string, user: object, organization: object }
400The request is invalid.Error
401Sign-in only: the email or password is incorrect (one fixed answer for both).Error
409Sign-up only: an account with that email already exists (`email_taken`).Error
413The request body is too large.Error
429Too many sign-up and sign-in attempts from this address: at most 10 every 10 minutes. `Retry-After` gives the seconds to wait.Error
503`busy`: too many password checks are waiting. Nothing was created or changed. `Retry-After: 5` gives the seconds to wait; try again.Error

Example

curl example for POST /v1/auth/signup
curl -X POST https://api.evictionsapi.com/v1/auth/signup \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Pat Landlord",
  "organizationName": "Acme Property",
  "email": "pat@example.com",
  "password": "a long passphrase, not this one"
}'

POST /v1/auth/login

Sign in with email and password. A wrong email and a wrong password get the identical `invalid_credentials` answer

Authentication: none

Request body

JSON. Fields not listed are rejected.

NameTypeRequiredDescription
emailstringYes1 to 254 characters.
passwordstringYes1 to 200 characters.

Responses

StatusMeaningBody
200A new session, with the user and organization. An `Idempotency-Key` header is ignored.{ token: string, user: object, organization: object }
400The request is invalid.Error
401Sign-in only: the email or password is incorrect (one fixed answer for both).Error
409Sign-up only: an account with that email already exists (`email_taken`).Error
413The request body is too large.Error
429Too many sign-up and sign-in attempts from this address: at most 10 every 10 minutes. `Retry-After` gives the seconds to wait.Error
503`busy`: too many password checks are waiting. Nothing was created or changed. `Retry-After: 5` gives the seconds to wait; try again.Error

Example

curl example for POST /v1/auth/login
curl -X POST https://api.evictionsapi.com/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{
  "email": "pat@example.com",
  "password": "a long passphrase, not this one"
}'

POST /v1/public/leads

Send a website request: access, a partner-attorney application, or a message. No credential; browser calls are allowed from the website origin only

Authentication: none

Request body

JSON. The body is one of these shapes. Fields not listed are rejected.

When kind is "access_request"

NameTypeRequiredDescription
kindstringYesAlways "access_request".
namestringYes1 to 120 characters.
emailstringYesFormat: email. Up to 254 characters. Pattern ^(?:[A-Za-z0-9_'+\-]+\.)*[A-Za-z0-9_'+\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$.
companystringNo1 to 200 characters.
rolestringNoOne of: "property_manager", "landlord", "developer", "attorney", "other".
statesarray of stringNo1 to 51 items.
messagestringNo1 to 4000 characters.
contact_urlstringNoHoneypot: leave empty. A request with this field filled in is acknowledged and discarded. Up to 0 characters.

When kind is "attorney_application"

NameTypeRequiredDescription
kindstringYesAlways "attorney_application".
namestringYes1 to 120 characters.
emailstringYesFormat: email. Up to 254 characters. Pattern ^(?:[A-Za-z0-9_'+\-]+\.)*[A-Za-z0-9_'+\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$.
companystringNo1 to 200 characters.
statesarray of stringYes1 to 51 items.
barNumberstringYes1 to 60 characters.
messagestringNo1 to 4000 characters.
contact_urlstringNoHoneypot: leave empty. A request with this field filled in is acknowledged and discarded. Up to 0 characters.

When kind is "contact"

NameTypeRequiredDescription
kindstringYesAlways "contact".
namestringYes1 to 120 characters.
emailstringYesFormat: email. Up to 254 characters. Pattern ^(?:[A-Za-z0-9_'+\-]+\.)*[A-Za-z0-9_'+\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$.
messagestringYes1 to 4000 characters.
contact_urlstringNoHoneypot: leave empty. A request with this field filled in is acknowledged and discarded. Up to 0 characters.

Responses

StatusMeaningBody
202The request was received. A request with the `contact_url` honeypot field filled in gets the same answer and is discarded.{ received: boolean }
400The request is invalid.Error
413The request body is too large.Error
429Too many requests from this address: at most 5 every 10 minutes. `Retry-After` gives the seconds to wait.Error

Example

curl example for POST /v1/public/leads
curl -X POST https://api.evictionsapi.com/v1/public/leads \
  -H "Content-Type: application/json" \
  -d '{
  "kind": "access_request",
  "name": "Pat Landlord",
  "email": "pat@example.com",
  "role": "landlord",
  "states": ["FL"]
}'

Partner attorney endpoints

Used by the licensed partner attorneys who review cases, with an attorney token. An API key cannot call them. Customers integrating the API do not need them; they are listed so the reference is complete.

GET /v1/attorney/queue

Cases awaiting the attorney's review, and assigned cases that need attention

Authentication: Partner attorney token, as Authorization: Bearer eut_...

Responses

StatusMeaningBody
200Cases in notice or filing review, and open cases on hold or with a failed job, oldest first.{ items: AttorneyQueueItem[] }
400The request is invalid.Error
401The credential is missing or invalid.Error
403The credential is not allowed to do this.Error
404Not found.Error
409The request conflicts with the current state: for a case, it is not in a state that allows this; for an API key, a limit or the key in use.Error
422The case did not pass a check.Error

Example

curl example for GET /v1/attorney/queue
curl https://api.evictionsapi.com/v1/attorney/queue \
  -H "Authorization: Bearer eut_..."

GET /v1/attorney/cases/{id}

A case with its documents, evidence, gate results, filings, service attempts and full audit trail; the access is audited

Authentication: Partner attorney token, as Authorization: Bearer eut_...

Parameters

NameInTypeRequiredDescription
idpathstringYesThe case id.

Responses

StatusMeaningBody
200The case in attorney detail.AttorneyCase
400The request is invalid.Error
401The credential is missing or invalid.Error
403The credential is not allowed to do this.Error
404Not found.Error
409The request conflicts with the current state: for a case, it is not in a state that allows this; for an API key, a limit or the key in use.Error
422The case did not pass a check.Error

Example

curl example for GET /v1/attorney/cases/{id}
curl https://api.evictionsapi.com/v1/attorney/cases/case_... \
  -H "Authorization: Bearer eut_..."

GET /v1/attorney/cases/{id}/documents/{docId}

Download a document; the access is audited

Authentication: Partner attorney token, as Authorization: Bearer eut_...

Parameters

NameInTypeRequiredDescription
idpathstringYesThe case id.
docIdpathstringYesThe document id.

Responses

StatusMeaningBody
200The document bytes.binaryapplication/pdf
400The request is invalid.Error
401The credential is missing or invalid.Error
403The credential is not allowed to do this.Error
404Not found.Error
409The request conflicts with the current state: for a case, it is not in a state that allows this; for an API key, a limit or the key in use.Error
422The case did not pass a check.Error

Example

curl example for GET /v1/attorney/cases/{id}/documents/{docId}
curl https://api.evictionsapi.com/v1/attorney/cases/case_.../documents/doc_... \
  -H "Authorization: Bearer eut_..." \
  -o document.pdf

POST /v1/attorney/cases/{id}/reviews

Approve, reject or request changes, naming the document hashes reviewed

Authentication: Partner attorney token, as Authorization: Bearer eut_...

Parameters

NameInTypeRequiredDescription
idpathstringYesThe case id.

Request body

JSON. Fields not listed are rejected.

NameTypeRequiredDescription
decisionstringYesOne of: "approve", "reject", "request_changes".
notesstringNo1 to 5000 characters.
documentHashesarray of stringYesUp to 50 items.

Responses

StatusMeaningBody
200The case after the decision.Case
400The request is invalid.Error
401The credential is missing or invalid.Error
403The credential is not allowed to do this.Error
404Not found.Error
409The request conflicts with the current state: for a case, it is not in a state that allows this; for an API key, a limit or the key in use.Error
422The case did not pass a check.Error

Example

curl example for POST /v1/attorney/cases/{id}/reviews
curl -X POST https://api.evictionsapi.com/v1/attorney/cases/case_.../reviews \
  -H "Authorization: Bearer eut_..." \
  -H "Content-Type: application/json" \
  -d '{
  "decision": "approve",
  "documentHashes": ["df75f3ea1d63370ba642bde84f53668817f063ac887beb86b8593d78cf5642b9"]
}'

POST /v1/attorney/cases/{id}/outcomes

Record a court outcome

Authentication: Partner attorney token, as Authorization: Bearer eut_...

Parameters

NameInTypeRequiredDescription
idpathstringYesThe case id.

Request body

JSON. The body is one of these shapes. Fields not listed are rejected.

When type is "hearing_scheduled"

NameTypeRequiredDescription
typestringYesAlways "hearing_scheduled".
datestringYes—

When type is "judgment"

NameTypeRequiredDescription
typestringYesAlways "judgment".
outcomestringYesOne of: "plaintiff", "defendant", "dismissed".

When type is "writ_requested"

NameTypeRequiredDescription
typestringYesAlways "writ_requested".

When type is "writ_issued"

NameTypeRequiredDescription
typestringYesAlways "writ_issued".

When type is "closed"

NameTypeRequiredDescription
typestringYesAlways "closed".

Responses

StatusMeaningBody
200The case after the outcome.Case
400The request is invalid.Error
401The credential is missing or invalid.Error
403The credential is not allowed to do this.Error
404Not found.Error
409The request conflicts with the current state: for a case, it is not in a state that allows this; for an API key, a limit or the key in use.Error
422The case did not pass a check.Error

Example

curl example for POST /v1/attorney/cases/{id}/outcomes
curl -X POST https://api.evictionsapi.com/v1/attorney/cases/case_.../outcomes \
  -H "Authorization: Bearer eut_..." \
  -H "Content-Type: application/json" \
  -d '{ "type": "hearing_scheduled", "date": "2026-11-02" }'

Response objects

The objects the partner attorney endpoints return. Response shapes are described by hand in the OpenAPI document and are deliberately loose.

AttorneyQueueItem

NameTypeRequiredDescription
idstringYes—
modestringYesOne of: "test", "live".
statestringYes—
groundstringYes—
entryPointstringYesOne of: "notice", "filing".
jurisdictionobjectYes—
jurisdiction.statestringYes—
jurisdiction.countystringNo—
attentionAttentionYes—
createdAtstringYesFormat: date-time.
updatedAtstringYesFormat: date-time.

Attention

Whether the case needs the attorney: it is on hold, or a job for it failed for good after its last state change.

NameTypeRequiredDescription
neededbooleanYes—
reasonsarray of stringYes—

AttorneyCase

The case as its assigned attorney sees it. Each read is recorded in the audit log as `tenant_data_viewed`.

NameTypeRequiredDescription
idstringYes—
modestringYesOne of: "test", "live".
statestringYesPosition in the case lifecycle, for example `notice_review` or `filing_submitted`.
heldFromstring | nullNo—
groundstringYes—
entryPointstringYesOne of: "notice", "filing".
courtCaseNumberstring | nullNo—
packVersionsobject | nullNo—
dataobjectYes—
deadlinesarray of objectYes—
deadlines[].namestringYes—
deadlines[].datestringYesFormat: date.
deadlines[].citationstringYes—
documentsarray of DocumentYes—
nextActionobjectYes—
nextAction.bystringYesOne of: "customer", "attorney", "platform", "court", "none".
nextAction.descriptionstringYes—
createdAtstringNoFormat: date-time.
updatedAtstringNoFormat: date-time.
gatesGateResultsYes—
evidencearray of DocumentYes—
filingsarray of FilingYesEvery court filing, oldest first.
serviceAttemptsarray of ServiceAttemptYesEvery service attempt, oldest first.
attentionAttentionYes—
eventsarray of EventYesThe full audit trail, including internal events.

Filing

A submission to the court. Attorney-only.

NameTypeRequiredDescription
idstringYes—
statusstringYes`submitted`, `accepted` or `rejected`.
envelopeIdstring | nullYes—
courtCaseNumberstring | nullYes—
rejectionReasonsarray | nullYesThe court's reasons, when it rejected the filing.
createdAtstringYesFormat: date-time.

ServiceAttempt

One request to serve a document on one defendant. Attorney-only.

NameTypeRequiredDescription
idstringYes—
stagestringYesOne of: "notice", "summons".
methodstringYes—
statusstringYes`pending`, `served` or `failed`.
servedDatestring | nullYesFormat: date.
failureReasonstring | nullYesThe process server's reason, when service failed.
createdAtstringYesFormat: date-time.

New to the API? Start with the quickstart, and see the webhooks guide for events.