# Deterministic integration workflows

Machine-readable workflows are published at `https://cleanedweb.com/arazzo.json`. OpenAPI
remains authoritative for individual operations.

## Exact count only

When the output is only "how many", run the `exactPropertyCount` workflow. It
resolves the maintained market and calls `countProperties` with the filters.
Do not call `searchProperties`, set a one-record limit, follow result cursors,
or download rich records just to derive the total. Require a non-negative
`total_matched` and a snapshot identity; the count consumes no delivery Units.

## Discover, search, validate, persist

Use this workflow only when the caller needs property records.

1. Fetch capabilities without using a cached marketing or coverage value.
2. Require a supported contract version and, for API-key or MCP access,
   `machine_access.enabled: true` plus non-empty `unit_costs`.
3. Fetch authenticated markets and require the requested market.
4. Resolve user-entered location text. If several candidates remain plausible, ask the user.
5. Create a unique idempotency key for the exact bounded request.
6. Submit `limit` and `max_units` with the search.
7. Apply every result-acceptance check before writing downstream.
8. Upsert by `property_entity_id`, retain `sources`, and store the usage receipt.

## True zero-result count or search

For count-only work, accept zero only when the exact count operation succeeded,
`total_matched` is zero, and the snapshot is present. For record retrieval,
accept an empty search only when HTTP succeeded, `returned` and `results.length`
are zero, `has_more` is false, `total_matched` is zero, the snapshot is present,
and the request was evaluated against an entitled ready market. Never convert
`401`, `403`, `429`, `503`, a network error, or a parsing error into empty success.

## Ambiguous location

Call location suggestions using the user's text. Present meaningful candidates and preserve
their `placeId`. Do not select a candidate merely because it is first. Resume the search with
both the original location text and the selected `location_place_id`.

## Idempotent recovery

After a timeout or retriable failure, resend the identical request with the identical key.
If the receipt reports `idempotentReplay: true`, continue using the recorded result and do not
perform the downstream business effect twice. A new key is allowed only for a genuinely new
request.

## Current property and history

Retrieve the canonical property by `property_entity_id`, then request its newest-first changes
with a limit from 1 through 200. Finalized change history excludes suspected transitions and
incomplete observer runs. Re-read the property endpoint when current state matters.

## Webhook processing

1. Read the exact raw bytes.
2. Verify timestamp and every supported `v1` signature in constant time.
3. Claim `webhook-id` durably before the business effect.
4. Parse and validate `property-event-v1`.
5. Commit the effect and event claim in one transaction where possible.
6. Return `2xx`; for a duplicate committed ID, acknowledge without repeating the effect.

## Agent stop conditions

Stop or request human input for unsupported major versions, unsupported or unentitled markets,
ambiguous locations, duplicate canonical IDs, count mismatches, stale snapshots, unexpected
truncation, insufficient Units, a raised Unit ceiling, revoked authentication, or an unknown
error code.
