Appraisal Host - Appraisal Management Software for AMCs and Lenders

Developer documentation

OpenAPI 3.1 spec

Guide

Appraisal Host APIAuthenticationSandboxOrder lifecycleWebhooksReference notesChangelogSupport

API reference

Every endpoint

Sandbox

Build and test against the same contract you will use in production, with test data and without touching a real appraisal.

EnvironmentBase URL
Sandboxhttps://sandbox.api.appraisalhost.com/v1
Productionhttps://api.appraisalhost.com/v1

Getting access

Sandbox access is provisioned on request by our integrations team. There is no self serve signup, because every sandbox credential is tied to a test lender account we create for you.

Write to integrations@appraisalhost.com and tell us:

  1. Your company name and the product you are integrating.
  2. A technical contact: name, email, and time zone.
  3. Whether you will receive webhooks during the build, and the HTTPS URL to deliver them to. You can set or change this yourself later with PUT /webhook.
  4. Which order types you need in the sandbox catalog: at least one product on the current report standard, at least one on the prior standard, and a product with an FHA certification requirement if you will place those orders.

We reply with a client id, a client secret, and the sandbox order type codes. Keep the secret in a secret manager: it is shown once.

What the sandbox is

  • The same API, the same contract, the same error catalog, the same webhook signatures.
  • A test appraisal management company with a test lender account, a test order type catalog, and a test appraiser.
  • Your own data only. Nothing in the sandbox is shared with another partner.

Driving the sandbox

You drive the sandbox yourself. Two calls do it: one moves an order through the lifecycle, the other sends you a test delivery. Both are ordinary API calls, so your test suite runs a full lifecycle on every commit without anyone else being involved.

Move an order

POST /sandbox/orders/{order_id}/advance moves one of your sandbox orders to the status you name, and raises everything a real move raises: the same events, the same payloads, the same signed deliveries to your endpoint.

curl -s -X POST https://sandbox.api.appraisalhost.com/v1/sandbox/orders/ord_9TBK4C2QFA7M/advance \
  -H 'Authorization: Bearer aht_at_7Qk2rX9wTm4ZbN1sV6yH0pL8' \
  -H 'Content-Type: application/json' \
  -d '{ "to_status": "appraiser_assigned" }'

Three rules:

  1. It exists in the sandbox only. The same path in production returns 404.
  2. The transition table below is the whole rule for to_status. You may skip statuses, because a real order often does. You may not move an order backwards, you may not name the status the order is already at, and you may not reach pending_review, revision_requested, reconsideration_requested, on_hold, off_hold, cancelled or reactivated this way: those are produced by POST /orders, by POST /orders/{order_id}/revision-requests, and by hold, resume and cancel, which work in the sandbox exactly as they do in production. A move the table does not list is refused with 409 and code action_not_allowed_in_status, with the order's current status in current_status and the status you asked for in details[0].value.
  3. It fires the same notifications production fires, to the same endpoint, with the same signature.

What you may advance to, and from where

Current statusto_status you may name
pending_reviewnew
newappraiser_assigned, appraiser_accepted, borrower_contacted, left_message_for_borrower, appointment_scheduled, awaiting_review, report_rejected_for_correction, report_complete
appraiser_assignedappraiser_accepted, borrower_contacted, left_message_for_borrower, appointment_scheduled, awaiting_review, report_rejected_for_correction, report_complete
appraiser_acceptedborrower_contacted, left_message_for_borrower, appointment_scheduled, awaiting_review, report_rejected_for_correction, report_complete
borrower_contactedleft_message_for_borrower, appointment_scheduled, awaiting_review, report_rejected_for_correction, report_complete
left_message_for_borrowerborrower_contacted, appointment_scheduled, awaiting_review, report_rejected_for_correction, report_complete
appointment_scheduledawaiting_review, report_rejected_for_correction, report_complete
awaiting_reviewreport_rejected_for_correction, report_complete
report_rejected_for_correctionawaiting_review, report_complete
report_completeNothing. Open a correction or a reconsideration first, which moves the order to revision_requested or reconsideration_requested.
revision_requestedrevised_report_complete
reconsideration_requestedrevised_report_complete
revised_report_completeNothing. Open another correction first.
on_hold, cancelledNothing. Resume a held order first; a cancelled order is not advanced.

An order at off_hold or reactivated may be advanced to whatever the table allows for the status it held before the hold or the cancellation, which the hold and cancel responses give you in previous_status.

A sequence that exercises the whole contract, step by step against the table above:

  1. Place an order with POST /orders. It is created at new, and order.created fires. An order the company would review first is created at pending_review: advance it to new before the rest of the sequence.
  2. Advance to appraiser_assigned: you receive order.assigned and order.status_changed.
  3. Advance to appointment_scheduled, skipping appraiser_accepted and the borrower contact statuses, which the table allows and a real order often does. Then advance to awaiting_review.
  4. Advance to report_complete: you receive order.completed with every delivered document listed, plus order.document_added for each file.
  5. Open a revision request, which moves the order to revision_requested, then advance to revised_report_complete: you receive order.revision_requested, order.revision_responded, and a second order.completed with revision set to true.
  6. On separate orders, call hold, resume and cancel to exercise the 409 rules and the remaining events. The advance call cannot set those statuses.

Send yourself a test delivery

POST /webhook/test delivers one signed specimen event to your configured endpoint and returns what your endpoint answered. It is how you prove your signature check, your timestamp tolerance and your ten second acknowledgement before you place an order at all.

curl -s -X POST https://sandbox.api.appraisalhost.com/v1/webhook/test \
  -H 'Authorization: Bearer aht_at_7Qk2rX9wTm4ZbN1sV6yH0pL8' \
  -H 'Content-Type: application/json' \
  -d '{ "type": "order.status_changed" }'
{
  "event_id": "evt_01M2TM1N60M4HGM9QGTHVCDMA2",
  "type": "order.status_changed",
  "url": "https://los.example.com/hooks/appraisal-host",
  "delivered": true,
  "response_status": 200,
  "response_time_ms": 142,
  "attempted_at": "2026-09-18T16:02:04Z"
}

The delivery is signed with your current secret and carries the same headers as a real one. Its envelope carries "test": true, and it is not written to your feed, so GET /events is unaffected. Its payload carries a synthetic order_id, always prefixed ord_test_, which no real order in any environment ever carries, so a specimen can never be mistaken for one of your orders. POST /webhook/test works in production too, on the same terms: see Webhooks for what a handler does with it.

What differs from production

DifferenceDetail
No real peopleNo email or message ever reaches a real borrower, agent or appraiser. Notifications stay inside the sandbox.
Test data onlyUse fictional borrowers and fictional contact details. The sandbox is for test data only: real borrower data belongs in production.
Test documentsDelivered reports, invoices and certificates are sample files with the right shape, the right media type and the right document kinds. They are not real appraisals and carry no opinion of value you should read.
Test catalogOrder type codes, loan types and add-ons are ours, not a real company's. Production codes come from the appraisal management company you will serve, and are read from GET /order-types, never hard coded.
AdvancingSandbox orders move when you call POST /sandbox/orders/{order_id}/advance, in the sequence you are testing, rather than on a clock.
Rate limitThe same 600 requests per minute, so that your retry and backoff behavior is tested honestly.
Data retentionSandbox orders and events may be cleared when an integration goes quiet for a long period. Nothing there is a record of anything.

A checklist before you go live

Work through this in the sandbox. It is the same list our integrations team walks with you before we hand over production credentials.

  • The lender account you will use in production is one the appraisal management company invoices, rather than one that pays per order by card.
  • You read GET /order-types and send codes from it, rather than codes written into your source.
  • You send an Idempotency-Key on every create, and you handle the 409 for a reused key.
  • You store our id for every order and document against your own loan file.
  • You handle every status code in the catalog, including statuses your first test happened not to produce, and you branch on code rather than on label.
  • You verify the webhook signature, reject a stale timestamp, and return a 2xx within 10 seconds before doing your own work.
  • Your webhook handler is idempotent on the event id, and tolerates events arriving out of order.
  • You can catch up from GET /events after your listener has been down.
  • You handle 401 with one token refresh and retry, and stop on a revoked client.
  • You handle 429 with Retry-After.
  • You download documents through a fresh signed link rather than storing links, and you handle all the document kinds your products deliver.
  • You parse a report_data file in every report format your products are delivered in.
  • You call GET /account at start-up for each credential and assert the lender it names against your own configuration.

Moving to production

Production credentials are issued by the appraisal management company you are integrating for, not by us. When your sandbox run is complete, tell us and we will introduce you. Change the base URL and the credential: nothing else in your integration changes.

AuthenticationOrder lifecycle
Appraisal Host - Appraisal Management Software for AMCs and Lenders

Platform

  • Features
  • Integrations
  • Pricing

Solutions

  • For AMCs
  • For Lenders
  • For Appraisal Companies
  • For Non-QM Lenders
  • For Banks
  • For Credit Unions

Resources

  • Tools
  • Developers
  • Blog
  • FAQ
  • Support
  • Compliance & Regulations

Company

  • About
  • Contact

Appraisal Host

1 Washington Mall #1105

Boston, MA 02108

© 2026 Appraisal Host

|Privacy Policy|Terms of Service|SMS Consent

appraisalhost.com is a service of Appraisal Host LLC.

Powered byOptiWork.ai