API reference
The Appraisal Host API lets a loan origination system, a point of sale, or any ordering platform place appraisal orders with an appraisal management company that runs on Appraisal Host, follow each order through its lifecycle, exchange messages and documents, and receive the finished report package.
One address serves every appraisal management company on the platform. Each credential we issue belongs to one lender account at one company, so the credential itself tells us where the order belongs. You store one base URL and one credential per lender you serve.
Conventions used throughout:
- JSON request and response bodies, UTF-8.
- Identifiers are opaque prefixed strings (
ord_,doc_,msg_,rr_,evt_,cli_). Treat them as strings of up to 64 characters and do not parse them. - Timestamps are ISO-8601 in UTC, for example
2026-09-17T14:32:05Z. Dates without a time areYYYY-MM-DD. - Money is a decimal string with a separate currency code, for example
"525.00"with"USD". We never send money as a floating point number. - Every error shares one body shape:
code,message, an optionaldetailsarray, and acorrelation_idyou can quote to our integrations team. - List endpoints return a
dataarray withpage,per_page,totalandtotal_pages. The event feed uses a cursor instead.
The full guide, including sandbox access and webhook verification samples, is published at https://www.appraisalhost.com/developers and this document is downloadable at https://www.appraisalhost.com/developers/spec/openapi.json.
Production
https://api.appraisalhost.com/v1Sandbox. Access is provisioned on request by our integrations team.
https://sandbox.api.appraisalhost.com/v1This page is generated from the published contract. The same document is available as a file at /developers/spec/openapi.json for client generation and API tooling.
Service
/pingLiveness check
Returns 200 while the API is serving traffic. No credential is required, and the response never contains account data. Use it in your own monitoring.
Responses
{
"status": "ok",
"time": "2026-09-17T14:32:05Z"
}Retry-After and retry.Example error body
{
"code": "rate_limited",
"message": "Too many requests. Retry after 30 seconds.",
"correlation_id": "req_01J9Z48F4H7K0M3P6R9T2W5Y"
}Idempotency-Key. For a write that takes no key, such as a message, an
upload or a revision request, read the order first rather than sending it
again. Quote the correlation_id to our integrations team.Example error body
{
"code": "internal_error",
"message": "The request could not be completed. Quote the correlation id if it continues.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}Retry-After and retry.Example error body
{
"code": "service_unavailable",
"message": "The API is briefly unavailable. Retry after the interval in Retry-After.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}Authentication
/oauth/tokenGet an access token
Exchange your client id and client secret for a bearer token. The token is
opaque, is valid for 60 minutes, and carries the lender scope. Request a
new token shortly before the old one expires, or when a call returns 401
with code token_expired. Tokens are not revoked when you request a new
one, so a rolling refresh is safe.
This is an OAuth 2.0 client credentials token endpoint. It accepts
application/x-www-form-urlencoded, with client_id and client_secret
either in the body or in an HTTP Basic header, and it also accepts a JSON
body of the same fields. Never place a client secret in a URL or in a
query string.
Errors here, and only here, use the RFC 6749 shape (error,
error_description) rather than this API's standard error body, so that a
standard client library can classify them. Every other endpoint answers
with the standard error body.
Request bodyrequired
Accepted content types: application/x-www-form-urlencoded or application/json
| Field | Type | Description |
|---|---|---|
grant_typerequired | string | |
client_idrequired | string | The client id we issued. Always starts with cli_. |
client_secretrequired | string | The client secret we issued. Shown once, at creation. Store it in a secret manager. |
scope | string | Optional. The only scope in version 1 is lender, which is also the default. |
Example request
{
"grant_type": "client_credentials",
"client_id": "cli_example_2f8c41",
"client_secret": "example_secret_do_not_use_9f4b1c77ae"
}Responses
{
"access_token": "aht_at_7Qk2rX9wTm4ZbN1sV6yH0pL8",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "lender"
}grant_type, or a missing credential. RFC 6749 shape.Example error body
{
"error": "invalid_request",
"error_description": "grant_type must be client_credentials.",
"correlation_id": "req_01J9Z2A7K3M5P8R1T4W6Y9B2D"
}Example error body
{
"error": "invalid_client",
"error_description": "The client id or client secret is not valid.",
"correlation_id": "req_01J9Z2A7K3M5P8R1T4W6Y9B2D"
}Content-Type is not supported. JSON endpoints require
application/json; the upload endpoint requires multipart/form-data
with a file of an accepted type.Example error body
{
"code": "unsupported_media_type",
"message": "Send application/json.",
"correlation_id": "req_01J9Z46B0D3F6H9K2M5P8R1T"
}Retry-After and retry.Example error body
{
"code": "rate_limited",
"message": "Too many requests. Retry after 30 seconds.",
"correlation_id": "req_01J9Z48F4H7K0M3P6R9T2W5Y"
}Idempotency-Key. For a write that takes no key, such as a message, an
upload or a revision request, read the order first rather than sending it
again. Quote the correlation_id to our integrations team.Example error body
{
"code": "internal_error",
"message": "The request could not be completed. Quote the correlation id if it continues.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}Retry-After and retry.Example error body
{
"code": "service_unavailable",
"message": "The API is briefly unavailable. Retry after the interval in Retry-After.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}/accountRead what this credential is for
Returns the lender account and the appraisal management company this credential belongs to, the environment it works in, the scopes it carries and its rate limit.
Call it at start-up for every credential you hold, and check lender.id
and lender.name against your own configuration before you place an order
with it. A credential mapped to the wrong lender would place that lender's
borrower on another lender's account, and this is the check that catches
it.
Responses
{
"client_id": "cli_example_2f8c41",
"environment": "production",
"lender": {
"id": "len_4WQ2H8ZKPB31",
"name": "Example Mortgage Group"
},
"company": {
"id": "cmp_7YT5M2XRND94",
"name": "Example Appraisal Management"
},
"scopes": [
"lender"
],
"rate_limit": {
"requests_per_minute": 600
}
}Example error body
{
"code": "token_expired",
"message": "The access token has expired.",
"correlation_id": "req_01J9Z41P0R3T6W9Y2B5D8F1H"
}Retry-After and retry.Example error body
{
"code": "rate_limited",
"message": "Too many requests. Retry after 30 seconds.",
"correlation_id": "req_01J9Z48F4H7K0M3P6R9T2W5Y"
}Idempotency-Key. For a write that takes no key, such as a message, an
upload or a revision request, read the order first rather than sending it
again. Quote the correlation_id to our integrations team.Example error body
{
"code": "internal_error",
"message": "The request could not be completed. Quote the correlation id if it continues.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}Retry-After and retry.Example error body
{
"code": "service_unavailable",
"message": "The API is briefly unavailable. Retry after the interval in Retry-After.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}Order Types
/order-typesList the products this lender may order
Returns the order types available to your lender account, the report format each one is delivered in, and, for products on the current report standard, the loan types and add-ons that may be attached.
Read this endpoint before you place an order. It is the only place that
tells you, in advance, which documents will come back and which
loan_type_code and add_on_codes values the product accepts. Codes are
stable for each appraisal management company; names are display text and may be reworded. The list is
ordered by code, ascending.
A product this lender is not entitled to order does not appear here at
all. A product the company has withdrawn appears with active: false and
cannot be ordered.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
page | query | integer | The page to return, starting at 1. |
per_page | query | integer | How many items to return per page, from 1 to 100. |
has_adu | query | boolean | Which add-ons to list. The default, false, lists the add-ons that apply to a property without an accessory dwelling unit. True lists those same add-ons plus the ones that apply only when the property has one. |
report_format | query | string enum | Return only order types delivered in this report format. |
Responses
{
"data": [
{
"code": "SFR-1004-36",
"name": "Single Family Residential, current report standard",
"report_format": "uad_3_6",
"appraiser_certification": "none",
"active": true,
"loan_types": [
{
"code": "conventional",
"name": "Conventional"
},
{
"code": "conventional_new_construction",
"name": "Conventional, New Construction"
},
{
"code": "va",
"name": "VA"
}
],
"add_ons": [
{
"code": "rent_schedule",
"name": "Rent Schedule"
},
{
"code": "operating_income_statement",
"name": "Operating Income Statement"
}
],
"loan_purposes": [],
"property_types": [
"single_family",
"condominium",
"townhouse",
"two_to_four_unit_property"
]
},
{
"code": "SFR-1004-FHA",
"name": "Single Family Residential, FHA",
"report_format": "uad_3_6",
"appraiser_certification": "fha_required",
"active": true,
"loan_types": [
{
"code": "fha",
"name": "FHA"
}
],
"add_ons": [],
"loan_purposes": [],
"property_types": [
"single_family",
"condominium",
"townhouse"
]
},
{
"code": "DRIVEBY-2055",
"name": "Exterior Only Inspection",
"report_format": "uad_2_6",
"appraiser_certification": "none",
"active": true,
"loan_types": [],
"add_ons": [
{
"code": "rent_schedule",
"name": "Rent Schedule"
}
],
"loan_purposes": [
"purchase"
],
"property_types": []
}
],
"page": 1,
"per_page": 25,
"total": 3,
"total_pages": 1
}details names each field at fault.Example error body
{
"code": "validation_failed",
"message": "The request could not be processed. See details.",
"details": [
{
"field": "property.postal_code",
"code": "required",
"value": null,
"message": "A postal code is required."
},
{
"field": "loan.purpose",
"code": "invalid_value",
"value": "cash_out",
"message": "Must be one of: construction_only, construction_to_permanent, mortgage_modification, other, purchase, refinance."
}
],
"correlation_id": "req_01J9Z40M8P1R4T7W0Y3B6D9F"
}Example error body
{
"code": "token_expired",
"message": "The access token has expired.",
"correlation_id": "req_01J9Z41P0R3T6W9Y2B5D8F1H"
}Example error body
{
"code": "action_not_permitted_for_client",
"message": "This client is not permitted to cancel orders.",
"correlation_id": "req_01J9Z42R2T5W8Y1B4D7F0H3K"
}Retry-After and retry.Example error body
{
"code": "rate_limited",
"message": "Too many requests. Retry after 30 seconds.",
"correlation_id": "req_01J9Z48F4H7K0M3P6R9T2W5Y"
}Idempotency-Key. For a write that takes no key, such as a message, an
upload or a revision request, read the order first rather than sending it
again. Quote the correlation_id to our integrations team.Example error body
{
"code": "internal_error",
"message": "The request could not be completed. Quote the correlation id if it continues.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}Retry-After and retry.Example error body
{
"code": "service_unavailable",
"message": "The API is briefly unavailable. Retry after the interval in Retry-After.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}Orders
/ordersList orders
Returns the orders that belong to your lender account, ordered by
created_at descending with id as the tie break.
Filter by one or more status codes, and by updated_since to poll for
change. updated_since is inclusive to the second, so overlap your
windows by a second or two rather than trusting exact boundaries.
Webhooks remain the primary way to learn about change: this endpoint is
for reconciliation and for catching up.
Page numbers walk a collection that can change while you read it, so an order touched between your first page and your last can move. Walk every page quickly, then run the same window again and compare the two runs: when they agree, nothing moved underneath you.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
page | query | integer | The page to return, starting at 1. |
per_page | query | integer | How many items to return per page, from 1 to 100. |
status | query | string | One or more status codes, comma separated. See the status catalog in
the schema OrderStatusCode. |
updated_since | query | string (date-time) | Return only orders changed at or after this instant. updated_at
moves when anything you can see on the order changes: its status, its
dates, its fee, its documents, its messages and its own fields. |
order_number | query | string | Return the order carrying this order number from the appraisal management company. |
lender_reference | query | string | Return orders carrying this reference of yours. |
Responses
{
"data": [
{
"id": "ord_9TBK4C2QFA7M",
"order_number": "2026-1043",
"lender_reference": "LN-2026-88421",
"status": {
"code": "appraiser_assigned",
"label": "Appraiser Assigned",
"changed_at": "2026-09-18T13:04:11Z"
},
"order_type": {
"code": "SFR-1004-36",
"name": "Single Family Residential, current report standard",
"report_format": "uad_3_6",
"appraiser_certification": "none"
},
"property_address_summary": "100 Example Avenue, Springfield, IL 62701",
"dates": {
"created_at": "2026-09-17T14:32:05Z",
"updated_at": "2026-09-18T13:04:11Z",
"due_date": "2026-10-02",
"appointment_at": null,
"completed_at": null
}
}
],
"page": 1,
"per_page": 25,
"total": 1,
"total_pages": 1
}details names each field at fault.Example error body
{
"code": "validation_failed",
"message": "The request could not be processed. See details.",
"details": [
{
"field": "property.postal_code",
"code": "required",
"value": null,
"message": "A postal code is required."
},
{
"field": "loan.purpose",
"code": "invalid_value",
"value": "cash_out",
"message": "Must be one of: construction_only, construction_to_permanent, mortgage_modification, other, purchase, refinance."
}
],
"correlation_id": "req_01J9Z40M8P1R4T7W0Y3B6D9F"
}Example error body
{
"code": "token_expired",
"message": "The access token has expired.",
"correlation_id": "req_01J9Z41P0R3T6W9Y2B5D8F1H"
}Example error body
{
"code": "action_not_permitted_for_client",
"message": "This client is not permitted to cancel orders.",
"correlation_id": "req_01J9Z42R2T5W8Y1B4D7F0H3K"
}Example error body
{
"code": "semantic_validation_failed",
"message": "The loan type does not apply to this order type.",
"details": [
{
"field": "loan_type_code",
"code": "not_applicable",
"value": "va",
"message": "That loan type is not available on order type SFR-1004-FHA. Read GET /order-types for the loan types the product accepts."
}
],
"correlation_id": "req_01J9Z47D2F5H8K1M4P7R0T3W"
}Retry-After and retry.Example error body
{
"code": "rate_limited",
"message": "Too many requests. Retry after 30 seconds.",
"correlation_id": "req_01J9Z48F4H7K0M3P6R9T2W5Y"
}Idempotency-Key. For a write that takes no key, such as a message, an
upload or a revision request, read the order first rather than sending it
again. Quote the correlation_id to our integrations team.Example error body
{
"code": "internal_error",
"message": "The request could not be completed. Quote the correlation id if it continues.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}Retry-After and retry.Example error body
{
"code": "service_unavailable",
"message": "The API is briefly unavailable. Retry after the interval in Retry-After.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}/ordersPlace an order
Places a new appraisal order for your lender account at its appraisal management company.
Send order_type_code from GET /order-types. For a product on the
current report standard, also send loan_type_code, and add_on_codes
when you need them: both are validated against the product, and an unknown
or inapplicable code is refused with 422 rather than being guessed at.
property.postal_code is required. City, state and county are filled in
from the postal code when you leave them out.
Always send an Idempotency-Key. We keep the key for 24 hours: a repeat of
the same key with the same body returns the original order instead of
creating a second one, and a repeat with a different body is refused with
409 and code idempotency_key_reused.
A create returns 201 and the order. An order we can place straight away is
at new and stays there until the appraisal management company assigns an
appraiser. An order that needs a review by the company first, for example
an unusual product, loan type or property, is at pending_review and moves
to new when the company places it. Both are normal, and you will see
order.status_changed when the order moves on. A request we can refuse
deterministically, such as an unknown code or a code that does not apply to
the product, is refused with 422 instead and no order is created.
We never accept card details. API ordering requires a lender account the
appraisal management company invoices. An account that pays for each order
by card is refused with 403 and code account_not_billable: ask the
company to put the account on invoicing first.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
Idempotency-Key | header | string | A unique key of your own, up to 128 characters, that makes this create
safe to retry. We remember the key and its result for 24 hours.
A key is scoped to your client credential and to this endpoint: the same
key sent by another credential is a different key. A repeat with the same
key and the same body returns the original order with the original 201. A
repeat with the same key and a different body is refused with 409 and code
idempotency_key_reused. |
Request bodyrequired
Content type: application/json
| Field | Type | Description |
|---|---|---|
order_type_coderequired | string | The product to order, from GET /order-types. |
loan_type_code | string or null | The loan type tier, from the product's loan_types. Required when the
product lists loan types. An unknown or inapplicable code is refused
with 422 rather than being guessed at. |
add_on_codes | array of string | Add-ons to attach, from the product's add_ons. |
due_daterequired | string (date) | The date the lender needs the report by. The appraisal management company confirms or adjusts it. |
lender_reference | string or null | Your own reference for this order. We store it and return it, and you can search on it. |
rush | boolean | |
complex | boolean | |
rural | boolean | |
priority | boolean | |
certified_appraiser_required | boolean | |
appraiser_instructions | string or null | Access instructions and anything else the appraiser needs to know. |
loanrequired | LoanCreate | The loan the appraisal supports. |
propertyrequired | PropertyCreate | The property to be appraised. |
borrowersrequired | array of BorrowerOrCoBorrower | The borrower, and a co-borrower when there is one. |
parties | Parties | Other people involved in the order. |
notes | array of Note | |
documents | array of InlineDocument | Supporting documents to attach at create, base64 encoded. Prefer
POST /orders/{order_id}/documents for anything over a megabyte or
two. |
Example: A product on the current report standard, with a loan type and an add-on
{
"order_type_code": "SFR-1004-36",
"loan_type_code": "conventional",
"add_on_codes": [
"rent_schedule"
],
"due_date": "2026-10-02",
"rush": false,
"complex": false,
"rural": false,
"priority": false,
"certified_appraiser_required": true,
"appraiser_instructions": "Gate code 4417. Call the listing agent for access.",
"lender_reference": "LN-2026-88421",
"loan": {
"purpose": "purchase",
"number": "88421",
"client": "Example Mortgage Group",
"investor": "Example Investor Trust",
"purchase_price": "415000.00",
"currency": "USD"
},
"property": {
"address": {
"street": "100 Example Avenue",
"unit": "Unit 2",
"city": "Springfield",
"state": "IL",
"postal_code": "62701",
"county": "Sangamon"
},
"type": "single_family",
"occupancy": "primary_residence",
"has_adu": true
},
"borrowers": [
{
"role": "borrower",
"first_name": "Sample",
"last_name": "Borrower",
"receives_report": false,
"receives_status_updates": true,
"address": {
"street": "300 Example Street",
"city": "Springfield",
"state": "IL",
"postal_code": "62703"
},
"contacts": [
{
"type": "email",
"role": "home",
"value": "sample.borrower@example.com"
},
{
"type": "phone",
"role": "cell",
"value": "+1-217-555-0142"
}
]
},
{
"role": "co_borrower",
"first_name": "Second",
"last_name": "Borrower",
"contacts": [
{
"type": "phone",
"role": "work",
"value": "+1-217-555-0143"
}
]
}
],
"parties": {
"real_estate_agent": {
"first_name": "Sample",
"last_name": "Agent",
"contacts": [
{
"type": "phone",
"role": "cell",
"value": "+1-217-555-0190"
}
]
},
"additional_contacts": [
{
"purpose": "status",
"name": "Processing Desk",
"email": "processing@example.com"
},
{
"purpose": "report",
"name": "Closing Desk",
"email": "closing@example.com"
}
]
},
"notes": [
{
"type": "order",
"text": "Borrower prefers a morning appointment."
},
{
"type": "appointment",
"text": "Dog on the property, please call ahead."
}
]
}Example: A product on the prior report standard, minimum fields
{
"order_type_code": "DRIVEBY-2055",
"due_date": "2026-09-30",
"loan": {
"purpose": "refinance",
"number": "88422"
},
"property": {
"address": {
"street": "200 Example Lane",
"postal_code": "62704"
},
"type": "condominium",
"occupancy": "second_home"
},
"borrowers": [
{
"role": "borrower",
"first_name": "Example",
"last_name": "Borrower",
"contacts": [
{
"type": "email",
"role": "home",
"value": "example.borrower@example.com"
}
]
}
]
}Responses
{
"id": "ord_9TBK4C2QFA7M",
"order_number": "2026-1043",
"lender_reference": "LN-2026-88421",
"status": {
"code": "new",
"label": "New Order",
"changed_at": "2026-09-17T14:32:05Z"
},
"order_type": {
"code": "SFR-1004-36",
"name": "Single Family Residential, current report standard",
"report_format": "uad_3_6",
"appraiser_certification": "none"
},
"loan": {
"purpose": "purchase",
"purpose_other": null,
"number": "88421",
"client": "Example Mortgage Group",
"investor": "Example Investor Trust",
"agency_case_number": null,
"fha_case_number": null,
"purchase_price": "415000.00",
"currency": "USD",
"loan_type": {
"code": "conventional",
"name": "Conventional"
},
"add_ons": [
{
"code": "rent_schedule",
"name": "Rent Schedule"
}
]
},
"property": {
"address": {
"street": "100 Example Avenue",
"unit": "Unit 2",
"city": "Springfield",
"state": "IL",
"postal_code": "62701",
"county": "Sangamon"
},
"type": "single_family",
"occupancy": "primary_residence",
"has_adu": true
},
"borrowers": [
{
"role": "borrower",
"first_name": "Sample",
"last_name": "Borrower",
"receives_report": false,
"receives_status_updates": true,
"address": {
"street": "300 Example Street",
"city": "Springfield",
"state": "IL",
"postal_code": "62703",
"county": "Sangamon"
},
"contacts": [
{
"type": "email",
"role": "home",
"value": "sample.borrower@example.com"
},
{
"type": "phone",
"role": "cell",
"value": "+1-217-555-0142"
}
]
},
{
"role": "co_borrower",
"first_name": "Second",
"last_name": "Borrower",
"receives_report": false,
"receives_status_updates": false,
"address": null,
"contacts": [
{
"type": "phone",
"role": "work",
"value": "+1-217-555-0143"
}
]
}
],
"parties": {
"real_estate_agent": {
"first_name": "Sample",
"last_name": "Agent",
"contacts": [
{
"type": "phone",
"role": "cell",
"value": "+1-217-555-0190"
}
]
},
"additional_contacts": [
{
"purpose": "status",
"name": "Processing Desk",
"email": "processing@example.com"
},
{
"purpose": "report",
"name": "Closing Desk",
"email": "closing@example.com"
}
]
},
"notes": [
{
"type": "order",
"text": "Borrower prefers a morning appointment."
},
{
"type": "appointment",
"text": "Dog on the property, please call ahead."
}
],
"flags": {
"rush": false,
"complex": false,
"rural": false,
"priority": false,
"certified_appraiser_required": true
},
"appraiser_instructions": "Gate code 4417. Call the listing agent for access.",
"appraiser": null,
"dates": {
"created_at": "2026-09-17T14:32:05Z",
"updated_at": "2026-09-17T14:32:05Z",
"due_date": "2026-10-02",
"appointment_at": null,
"completed_at": null
},
"fees": {
"appraisal_fee": "525.00",
"currency": "USD"
},
"documents": []
}details names each field at fault.Example error body
{
"code": "validation_failed",
"message": "The request could not be processed. See details.",
"details": [
{
"field": "property.postal_code",
"code": "required",
"value": null,
"message": "A postal code is required."
},
{
"field": "loan.purpose",
"code": "invalid_value",
"value": "cash_out",
"message": "Must be one of: construction_only, construction_to_permanent, mortgage_modification, other, purchase, refinance."
}
],
"correlation_id": "req_01J9Z40M8P1R4T7W0Y3B6D9F"
}Example error body
{
"code": "token_expired",
"message": "The access token has expired.",
"correlation_id": "req_01J9Z41P0R3T6W9Y2B5D8F1H"
}Example error body
{
"code": "account_not_billable",
"message": "This lender account is billed per order by card and cannot order through the API.",
"correlation_id": "req_01J9Z2CF8H4N7Q0S3V6X9A2C5"
}Idempotency-Key was already used with a different body.Example error body
{
"code": "idempotency_key_reused",
"message": "This Idempotency-Key was used for a different request within the last 24 hours.",
"correlation_id": "req_01J9Z2CF8H4N7Q0S3V6X9A2C5"
}Example error body
{
"code": "payload_too_large",
"message": "The file is larger than the 25 MB limit.",
"correlation_id": "req_01J9Z45Y8B1D4F7H0K3M6P9R"
}Content-Type is not supported. JSON endpoints require
application/json; the upload endpoint requires multipart/form-data
with a file of an accepted type.Example error body
{
"code": "unsupported_media_type",
"message": "Send application/json.",
"correlation_id": "req_01J9Z46B0D3F6H9K2M5P8R1T"
}Example error body
{
"code": "semantic_validation_failed",
"message": "The loan type does not apply to this order type.",
"details": [
{
"field": "loan_type_code",
"code": "not_applicable",
"value": "va",
"message": "That loan type is not available on order type SFR-1004-FHA. Read GET /order-types for the loan types the product accepts."
}
],
"correlation_id": "req_01J9Z47D2F5H8K1M4P7R0T3W"
}Retry-After and retry.Example error body
{
"code": "rate_limited",
"message": "Too many requests. Retry after 30 seconds.",
"correlation_id": "req_01J9Z48F4H7K0M3P6R9T2W5Y"
}Idempotency-Key. For a write that takes no key, such as a message, an
upload or a revision request, read the order first rather than sending it
again. Quote the correlation_id to our integrations team.Example error body
{
"code": "internal_error",
"message": "The request could not be completed. Quote the correlation id if it continues.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}Retry-After and retry.Example error body
{
"code": "service_unavailable",
"message": "The API is briefly unavailable. Retry after the interval in Retry-After.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}/orders/{order_id}Read an order
Returns the full order, its current status, the documents on it, and the fee the lender is charged. You see exactly what the lender sees in the portal, with the same status wording, and nothing more.
Responses
{
"id": "ord_9TBK4C2QFA7M",
"order_number": "2026-1043",
"lender_reference": "LN-2026-88421",
"status": {
"code": "report_complete",
"label": "Report Complete",
"changed_at": "2026-09-29T18:12:44Z"
},
"order_type": {
"code": "SFR-1004-36",
"name": "Single Family Residential, current report standard",
"report_format": "uad_3_6",
"appraiser_certification": "none"
},
"loan": {
"purpose": "purchase",
"purpose_other": null,
"number": "88421",
"client": "Example Mortgage Group",
"investor": "Example Investor Trust",
"agency_case_number": null,
"fha_case_number": null,
"purchase_price": "415000.00",
"currency": "USD",
"loan_type": {
"code": "conventional",
"name": "Conventional"
},
"add_ons": [
{
"code": "rent_schedule",
"name": "Rent Schedule"
}
]
},
"property": {
"address": {
"street": "100 Example Avenue",
"unit": "Unit 2",
"city": "Springfield",
"state": "IL",
"postal_code": "62701",
"county": "Sangamon"
},
"type": "single_family",
"occupancy": "primary_residence",
"has_adu": true
},
"borrowers": [
{
"role": "borrower",
"first_name": "Sample",
"last_name": "Borrower",
"receives_report": false,
"receives_status_updates": true,
"address": null,
"contacts": [
{
"type": "email",
"role": "home",
"value": "sample.borrower@example.com"
}
]
}
],
"parties": {
"real_estate_agent": null,
"additional_contacts": []
},
"notes": [
{
"type": "order",
"text": "Borrower prefers a morning appointment."
}
],
"flags": {
"rush": false,
"complex": false,
"rural": false,
"priority": false,
"certified_appraiser_required": true
},
"appraiser_instructions": "Gate code 4417. Call the listing agent for access.",
"appraiser": {
"name": "J. Marsh"
},
"dates": {
"created_at": "2026-09-17T14:32:05Z",
"updated_at": "2026-09-29T18:12:44Z",
"due_date": "2026-10-02",
"appointment_at": "2026-09-22T15:00:00Z",
"completed_at": "2026-09-29T18:12:44Z"
},
"fees": {
"appraisal_fee": "525.00",
"currency": "USD"
},
"documents": [
{
"id": "doc_3XH8M1PLQW60",
"kind": "report_pdf",
"filename": "report_2026-1043.pdf",
"content_type": "application/pdf",
"size_bytes": 2841773,
"created_at": "2026-09-29T18:12:44Z"
},
{
"id": "doc_5RJ2N7VKTB41",
"kind": "report_data",
"filename": "report_2026-1043.zip",
"content_type": "application/zip",
"size_bytes": 1044210,
"created_at": "2026-09-29T18:12:44Z"
},
{
"id": "doc_8QL4P9WMYC72",
"kind": "invoice",
"filename": "invoice_2026-1043.pdf",
"content_type": "application/pdf",
"size_bytes": 88120,
"created_at": "2026-09-29T18:12:45Z"
}
]
}Example error body
{
"code": "token_expired",
"message": "The access token has expired.",
"correlation_id": "req_01J9Z41P0R3T6W9Y2B5D8F1H"
}Example error body
{
"code": "action_not_permitted_for_client",
"message": "This client is not permitted to cancel orders.",
"correlation_id": "req_01J9Z42R2T5W8Y1B4D7F0H3K"
}Example error body
{
"code": "not_found",
"message": "No order with that id.",
"correlation_id": "req_01J9Z43T4W7Y0B3D6F9H2K5M"
}Retry-After and retry.Example error body
{
"code": "rate_limited",
"message": "Too many requests. Retry after 30 seconds.",
"correlation_id": "req_01J9Z48F4H7K0M3P6R9T2W5Y"
}Idempotency-Key. For a write that takes no key, such as a message, an
upload or a revision request, read the order first rather than sending it
again. Quote the correlation_id to our integrations team.Example error body
{
"code": "internal_error",
"message": "The request could not be completed. Quote the correlation id if it continues.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}Retry-After and retry.Example error body
{
"code": "service_unavailable",
"message": "The API is briefly unavailable. Retry after the interval in Retry-After.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}/orders/{order_id}Amend an order
Amends the parts of an open order a lender may change: the loan number and your own reference, the contacts and parties, the notes, the appraiser instructions, and a request to move the due date.
A due date you send is a REQUEST. The appraisal management company confirms
or adjusts it, and the date on the order changes only when the company
accepts it. Watch
order.due_date_changed for the outcome.
The property, the borrower names, the order type, the loan type and the add-ons cannot be changed once an order exists. Cancel the order and place a new one instead. Amending a closed order is refused with 409.
Some companies do not let a lender amend an order at all. Then the call is
refused with 403 and code action_not_permitted_for_client, and the way to
ask is a message on the order.
Request bodyrequired
Content type: application/json
| Field | Type | Description |
|---|---|---|
lender_reference | string or null | |
due_date | string (date) | A REQUEST to move the due date. The date changes only when the appraisal management company accepts it. |
appraiser_instructions | string or null | |
loan | object | Only the loan number, the client and the investor may be changed. |
borrower_contacts | array of Contact | Replaces the borrower's contact list. Names and the property cannot be changed. |
parties | Parties | Other people involved in the order. |
notes | array of Note | Notes to add to the order. An order carries one note of each type, and what you send is added to the note of that type rather than replacing it. Nothing already on the order is removed. |
Example request
{
"lender_reference": "LN-2026-88421-R2",
"loan": {
"number": "88421-A"
},
"due_date": "2026-10-06",
"appraiser_instructions": "New gate code 8891.",
"notes": [
{
"type": "appointment",
"text": "Borrower now prefers afternoons."
}
],
"parties": {
"additional_contacts": [
{
"purpose": "status",
"name": "Processing Desk",
"email": "processing2@example.com"
}
]
}
}Responses
{
"id": "ord_9TBK4C2QFA7M",
"order_number": "2026-1043",
"lender_reference": "LN-2026-88421-R2",
"status": {
"code": "appraiser_assigned",
"label": "Appraiser Assigned",
"changed_at": "2026-09-18T13:04:11Z"
},
"order_type": {
"code": "SFR-1004-36",
"name": "Single Family Residential, current report standard",
"report_format": "uad_3_6",
"appraiser_certification": "none"
},
"loan": {
"purpose": "purchase",
"purpose_other": null,
"number": "88421-A",
"client": "Example Mortgage Group",
"investor": "Example Investor Trust",
"agency_case_number": null,
"fha_case_number": null,
"purchase_price": "415000.00",
"currency": "USD",
"loan_type": {
"code": "conventional",
"name": "Conventional"
},
"add_ons": []
},
"property": {
"address": {
"street": "100 Example Avenue",
"unit": "Unit 2",
"city": "Springfield",
"state": "IL",
"postal_code": "62701",
"county": "Sangamon"
},
"type": "single_family",
"occupancy": "primary_residence",
"has_adu": true
},
"borrowers": [],
"parties": {
"real_estate_agent": null,
"additional_contacts": [
{
"purpose": "status",
"name": "Processing Desk",
"email": "processing2@example.com"
}
]
},
"notes": [
{
"type": "appointment",
"text": "Borrower now prefers afternoons."
}
],
"flags": {
"rush": false,
"complex": false,
"rural": false,
"priority": false,
"certified_appraiser_required": true
},
"appraiser_instructions": "New gate code 8891.",
"appraiser": {
"name": "J. Marsh"
},
"dates": {
"created_at": "2026-09-17T14:32:05Z",
"updated_at": "2026-09-19T09:15:00Z",
"due_date": "2026-10-02",
"appointment_at": null,
"completed_at": null
},
"fees": {
"appraisal_fee": "525.00",
"currency": "USD"
},
"documents": []
}details names each field at fault.Example error body
{
"code": "validation_failed",
"message": "The request could not be processed. See details.",
"details": [
{
"field": "property.postal_code",
"code": "required",
"value": null,
"message": "A postal code is required."
},
{
"field": "loan.purpose",
"code": "invalid_value",
"value": "cash_out",
"message": "Must be one of: construction_only, construction_to_permanent, mortgage_modification, other, purchase, refinance."
}
],
"correlation_id": "req_01J9Z40M8P1R4T7W0Y3B6D9F"
}Example error body
{
"code": "token_expired",
"message": "The access token has expired.",
"correlation_id": "req_01J9Z41P0R3T6W9Y2B5D8F1H"
}Example error body
{
"code": "action_not_permitted_for_client",
"message": "This client is not permitted to cancel orders.",
"correlation_id": "req_01J9Z42R2T5W8Y1B4D7F0H3K"
}Example error body
{
"code": "not_found",
"message": "No order with that id.",
"correlation_id": "req_01J9Z43T4W7Y0B3D6F9H2K5M"
}Example error body
{
"code": "action_not_allowed_in_status",
"message": "A closed order cannot be amended.",
"current_status": "cancelled",
"details": [
{
"field": "status",
"code": "current_status",
"value": "cancelled",
"message": "The order has been cancelled."
}
],
"correlation_id": "req_01J9Z44W6Y9B2D5F8H1K4M7P"
}Content-Type is not supported. JSON endpoints require
application/json; the upload endpoint requires multipart/form-data
with a file of an accepted type.Example error body
{
"code": "unsupported_media_type",
"message": "Send application/json.",
"correlation_id": "req_01J9Z46B0D3F6H9K2M5P8R1T"
}Example error body
{
"code": "semantic_validation_failed",
"message": "The loan type does not apply to this order type.",
"details": [
{
"field": "loan_type_code",
"code": "not_applicable",
"value": "va",
"message": "That loan type is not available on order type SFR-1004-FHA. Read GET /order-types for the loan types the product accepts."
}
],
"correlation_id": "req_01J9Z47D2F5H8K1M4P7R0T3W"
}Retry-After and retry.Example error body
{
"code": "rate_limited",
"message": "Too many requests. Retry after 30 seconds.",
"correlation_id": "req_01J9Z48F4H7K0M3P6R9T2W5Y"
}Idempotency-Key. For a write that takes no key, such as a message, an
upload or a revision request, read the order first rather than sending it
again. Quote the correlation_id to our integrations team.Example error body
{
"code": "internal_error",
"message": "The request could not be completed. Quote the correlation id if it continues.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}Retry-After and retry.Example error body
{
"code": "service_unavailable",
"message": "The API is briefly unavailable. Retry after the interval in Retry-After.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}Order Actions
/orders/{order_id}/holdPlace an order on hold
Puts an open order on hold and stands the appraiser down. The appraiser is remembered, so resuming puts the order back where it was.
A hold is allowed while the order is open, is not already on hold, and no
report has been delivered. It is refused with 409 when the report has been
delivered (report_complete, revised_report_complete), a correction is
open (revision_requested), the order is cancelled, or it is already on
hold.
Send a reason: the appraisal management company and the appraiser both see it.
Request body
Content type: application/json
| Field | Type | Description |
|---|---|---|
reason | string |
Example request
{
"reason": "Borrower is renegotiating the purchase price."
}Responses
{
"id": "ord_9TBK4C2QFA7M",
"order_number": "2026-1043",
"status": {
"code": "on_hold",
"label": "On Hold",
"changed_at": "2026-09-19T11:02:00Z"
},
"previous_status": {
"code": "appraiser_assigned",
"label": "Appraiser Assigned"
}
}Example error body
{
"code": "token_expired",
"message": "The access token has expired.",
"correlation_id": "req_01J9Z41P0R3T6W9Y2B5D8F1H"
}Example error body
{
"code": "action_not_permitted_for_client",
"message": "This client is not permitted to cancel orders.",
"correlation_id": "req_01J9Z42R2T5W8Y1B4D7F0H3K"
}Example error body
{
"code": "not_found",
"message": "No order with that id.",
"correlation_id": "req_01J9Z43T4W7Y0B3D6F9H2K5M"
}Example error body
{
"code": "action_not_allowed_in_status",
"message": "An order with a delivered report cannot be placed on hold.",
"current_status": "report_complete",
"details": [
{
"field": "status",
"code": "current_status",
"value": "report_complete",
"message": "The report has already been delivered."
}
],
"correlation_id": "req_01J9Z3B2D5F8H1K4M7P0R3T6"
}Example error body
{
"code": "semantic_validation_failed",
"message": "The loan type does not apply to this order type.",
"details": [
{
"field": "loan_type_code",
"code": "not_applicable",
"value": "va",
"message": "That loan type is not available on order type SFR-1004-FHA. Read GET /order-types for the loan types the product accepts."
}
],
"correlation_id": "req_01J9Z47D2F5H8K1M4P7R0T3W"
}Retry-After and retry.Example error body
{
"code": "rate_limited",
"message": "Too many requests. Retry after 30 seconds.",
"correlation_id": "req_01J9Z48F4H7K0M3P6R9T2W5Y"
}Idempotency-Key. For a write that takes no key, such as a message, an
upload or a revision request, read the order first rather than sending it
again. Quote the correlation_id to our integrations team.Example error body
{
"code": "internal_error",
"message": "The request could not be completed. Quote the correlation id if it continues.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}Retry-After and retry.Example error body
{
"code": "service_unavailable",
"message": "The API is briefly unavailable. Retry after the interval in Retry-After.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}/orders/{order_id}/resumeTake an order off hold
Returns an order from hold to the point it had reached, and puts the remembered appraiser back on it. A resume is allowed while the order is on hold; any other status is refused with 409.
The order comes back at off_hold, which is transitional: it moves on to
its working status shortly afterwards, so read the order again rather than
treating off_hold as a resting state.
Request body
Content type: application/json
| Field | Type | Description |
|---|---|---|
reason | string |
Example request
{
"reason": "Purchase price agreed, please proceed."
}Responses
{
"id": "ord_9TBK4C2QFA7M",
"order_number": "2026-1043",
"status": {
"code": "off_hold",
"label": "Off Hold",
"changed_at": "2026-09-22T08:40:12Z"
},
"previous_status": {
"code": "on_hold",
"label": "On Hold"
}
}Example error body
{
"code": "token_expired",
"message": "The access token has expired.",
"correlation_id": "req_01J9Z41P0R3T6W9Y2B5D8F1H"
}Example error body
{
"code": "action_not_permitted_for_client",
"message": "This client is not permitted to cancel orders.",
"correlation_id": "req_01J9Z42R2T5W8Y1B4D7F0H3K"
}Example error body
{
"code": "not_found",
"message": "No order with that id.",
"correlation_id": "req_01J9Z43T4W7Y0B3D6F9H2K5M"
}Example error body
{
"code": "action_not_allowed_in_status",
"message": "Only an order that is on hold can be resumed.",
"current_status": "appraiser_assigned",
"details": [
{
"field": "status",
"code": "current_status",
"value": "appraiser_assigned",
"message": "The order is not on hold."
}
],
"correlation_id": "req_01J9Z3C4F7H0K3M6P9R2T5W8"
}Retry-After and retry.Example error body
{
"code": "rate_limited",
"message": "Too many requests. Retry after 30 seconds.",
"correlation_id": "req_01J9Z48F4H7K0M3P6R9T2W5Y"
}Idempotency-Key. For a write that takes no key, such as a message, an
upload or a revision request, read the order first rather than sending it
again. Quote the correlation_id to our integrations team.Example error body
{
"code": "internal_error",
"message": "The request could not be completed. Quote the correlation id if it continues.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}Retry-After and retry.Example error body
{
"code": "service_unavailable",
"message": "The API is briefly unavailable. Retry after the interval in Retry-After.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}/orders/{order_id}/cancelCancel an order
Cancels an open order. A cancellation is allowed while the order is open and no report has been delivered. It is refused with 409 when the report has been delivered, a correction is open, or the order is already cancelled. A held order must be resumed first.
Some companies do not allow a lender to cancel at all. In that case the
call is refused with 403 and code action_not_permitted_for_client, and
the way to ask is a message on the order.
Request body
Content type: application/json
| Field | Type | Description |
|---|---|---|
reason | string |
Example request
{
"reason": "Loan withdrawn by the borrower."
}Responses
{
"id": "ord_9TBK4C2QFA7M",
"order_number": "2026-1043",
"status": {
"code": "cancelled",
"label": "Order Cancelled",
"changed_at": "2026-09-20T16:22:31Z"
},
"previous_status": {
"code": "appointment_scheduled",
"label": "Appointment Scheduled"
}
}Example error body
{
"code": "token_expired",
"message": "The access token has expired.",
"correlation_id": "req_01J9Z41P0R3T6W9Y2B5D8F1H"
}Example error body
{
"code": "action_not_permitted_for_client",
"message": "This client is not permitted to cancel orders.",
"correlation_id": "req_01J9Z42R2T5W8Y1B4D7F0H3K"
}Example error body
{
"code": "not_found",
"message": "No order with that id.",
"correlation_id": "req_01J9Z43T4W7Y0B3D6F9H2K5M"
}Example error body
{
"code": "action_not_allowed_in_status",
"message": "An order with a delivered report cannot be cancelled.",
"current_status": "report_complete",
"details": [
{
"field": "status",
"code": "current_status",
"value": "report_complete",
"message": "The report has already been delivered."
}
],
"correlation_id": "req_01J9Z3D6H9K2M5P8R1T4W7Y0"
}Retry-After and retry.Example error body
{
"code": "rate_limited",
"message": "Too many requests. Retry after 30 seconds.",
"correlation_id": "req_01J9Z48F4H7K0M3P6R9T2W5Y"
}Idempotency-Key. For a write that takes no key, such as a message, an
upload or a revision request, read the order first rather than sending it
again. Quote the correlation_id to our integrations team.Example error body
{
"code": "internal_error",
"message": "The request could not be completed. Quote the correlation id if it continues.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}Retry-After and retry.Example error body
{
"code": "service_unavailable",
"message": "The API is briefly unavailable. Retry after the interval in Retry-After.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}Revision Requests
/orders/{order_id}/revision-requestsList the revision requests on an order
Returns every revision request on the order, ordered by created_at
descending with id as the tie break, with the company's responses and any
documents attached on either side.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
page | query | integer | The page to return, starting at 1. |
per_page | query | integer | How many items to return per page, from 1 to 100. |
Responses
{
"data": [
{
"id": "rr_6PD3K8YWQN25",
"order_id": "ord_9TBK4C2QFA7M",
"kind": "reconsideration_of_value",
"status": "accepted",
"reason": "Three closed sales within 0.4 miles support a higher value.",
"acknowledgements": {
"prior_appraisal_provided": false,
"comparable_sales_provided": true
},
"documents": [],
"responses": [
{
"id": "msg_4NF9R2XWTD86",
"created_at": "2026-09-30T15:41:00Z",
"author": {
"type": "manager",
"name": "Order Desk"
},
"message": "Sent to the appraiser for review. Revised report expected within two business days."
}
],
"created_at": "2026-09-30T10:04:18Z",
"updated_at": "2026-09-30T15:41:00Z"
}
],
"page": 1,
"per_page": 25,
"total": 1,
"total_pages": 1
}Example error body
{
"code": "token_expired",
"message": "The access token has expired.",
"correlation_id": "req_01J9Z41P0R3T6W9Y2B5D8F1H"
}Example error body
{
"code": "action_not_permitted_for_client",
"message": "This client is not permitted to cancel orders.",
"correlation_id": "req_01J9Z42R2T5W8Y1B4D7F0H3K"
}Example error body
{
"code": "not_found",
"message": "No order with that id.",
"correlation_id": "req_01J9Z43T4W7Y0B3D6F9H2K5M"
}Retry-After and retry.Example error body
{
"code": "rate_limited",
"message": "Too many requests. Retry after 30 seconds.",
"correlation_id": "req_01J9Z48F4H7K0M3P6R9T2W5Y"
}Idempotency-Key. For a write that takes no key, such as a message, an
upload or a revision request, read the order first rather than sending it
again. Quote the correlation_id to our integrations team.Example error body
{
"code": "internal_error",
"message": "The request could not be completed. Quote the correlation id if it continues.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}Retry-After and retry.Example error body
{
"code": "service_unavailable",
"message": "The API is briefly unavailable. Retry after the interval in Retry-After.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}/orders/{order_id}/revision-requestsRequest a correction or a reconsideration of value
Opens a revision request against a delivered report.
Two kinds are accepted. A correction asks the appraiser to fix or
clarify something in the report. A reconsideration_of_value asks the
appraiser to reconsider the opinion of value, and requires at least one
acknowledgement: that a prior appraisal was provided, or that comparable
sales were provided. Attach the sales or the prior report with
POST /orders/{order_id}/documents before you open the request, or send
them inline.
A request is accepted while the order is at report_complete,
revised_report_complete, revision_requested,
reconsideration_requested or cancelled. In any other status it is
refused with 409.
We fill the rest of the record the appraisal management company needs from
the order and your credential. If the order has no loan number, send
loan.number on the order first.
The appraisal management company may review the request before it reaches the appraiser. A request
therefore starts at submitted and moves to accepted or declined.
Watch order.revision_requested and order.revision_responded.
Request bodyrequired
Content type: application/json
| Field | Type | Description |
|---|---|---|
kindrequired | string enum | correction asks the appraiser to fix or clarify the report.
reconsideration_of_value asks the appraiser to reconsider the opinion of
value and requires at least one acknowledgement.One of: correction, reconsideration_of_value |
reasonrequired | string | What needs to change, and why. |
acknowledgements | RevisionAcknowledgements | Required on a reconsideration of value. At least one must be true, or the request is refused with 422. |
document_ids | array of string | Documents already uploaded to this order that support the request. |
documents | array of InlineDocument | Documents to attach inline instead of uploading first. |
Example: A correction
{
"kind": "correction",
"reason": "The gross living area on page 2 does not match the sketch."
}Example: A reconsideration of value with acknowledgements
{
"kind": "reconsideration_of_value",
"reason": "Three closed sales within 0.4 miles support a higher value.",
"acknowledgements": {
"prior_appraisal_provided": false,
"comparable_sales_provided": true
},
"document_ids": [
"doc_2KM7Q0VZTC93"
]
}Responses
{
"id": "rr_6PD3K8YWQN25",
"order_id": "ord_9TBK4C2QFA7M",
"kind": "reconsideration_of_value",
"status": "submitted",
"reason": "Three closed sales within 0.4 miles support a higher value.",
"acknowledgements": {
"prior_appraisal_provided": false,
"comparable_sales_provided": true
},
"documents": [
{
"id": "doc_2KM7Q0VZTC93",
"kind": "supporting",
"filename": "comparable_sales.pdf",
"content_type": "application/pdf",
"size_bytes": 412998,
"created_at": "2026-09-30T10:02:00Z"
}
],
"responses": [],
"created_at": "2026-09-30T10:04:18Z",
"updated_at": "2026-09-30T10:04:18Z"
}details names each field at fault.Example error body
{
"code": "validation_failed",
"message": "The request could not be processed. See details.",
"details": [
{
"field": "property.postal_code",
"code": "required",
"value": null,
"message": "A postal code is required."
},
{
"field": "loan.purpose",
"code": "invalid_value",
"value": "cash_out",
"message": "Must be one of: construction_only, construction_to_permanent, mortgage_modification, other, purchase, refinance."
}
],
"correlation_id": "req_01J9Z40M8P1R4T7W0Y3B6D9F"
}Example error body
{
"code": "token_expired",
"message": "The access token has expired.",
"correlation_id": "req_01J9Z41P0R3T6W9Y2B5D8F1H"
}Example error body
{
"code": "action_not_permitted_for_client",
"message": "This client is not permitted to cancel orders.",
"correlation_id": "req_01J9Z42R2T5W8Y1B4D7F0H3K"
}Example error body
{
"code": "not_found",
"message": "No order with that id.",
"correlation_id": "req_01J9Z43T4W7Y0B3D6F9H2K5M"
}Example error body
{
"code": "action_not_allowed_in_status",
"message": "A revision request can be opened only once a report has been delivered.",
"current_status": "appraiser_assigned",
"details": [
{
"field": "status",
"code": "current_status",
"value": "appraiser_assigned",
"message": "No report has been delivered on this order yet."
}
],
"correlation_id": "req_01J9Z3F8K1M4P7R0T3W6Y9B2"
}Content-Type is not supported. JSON endpoints require
application/json; the upload endpoint requires multipart/form-data
with a file of an accepted type.Example error body
{
"code": "unsupported_media_type",
"message": "Send application/json.",
"correlation_id": "req_01J9Z46B0D3F6H9K2M5P8R1T"
}Example error body
{
"code": "semantic_validation_failed",
"message": "The loan type does not apply to this order type.",
"details": [
{
"field": "loan_type_code",
"code": "not_applicable",
"value": "va",
"message": "That loan type is not available on order type SFR-1004-FHA. Read GET /order-types for the loan types the product accepts."
}
],
"correlation_id": "req_01J9Z47D2F5H8K1M4P7R0T3W"
}Retry-After and retry.Example error body
{
"code": "rate_limited",
"message": "Too many requests. Retry after 30 seconds.",
"correlation_id": "req_01J9Z48F4H7K0M3P6R9T2W5Y"
}Idempotency-Key. For a write that takes no key, such as a message, an
upload or a revision request, read the order first rather than sending it
again. Quote the correlation_id to our integrations team.Example error body
{
"code": "internal_error",
"message": "The request could not be completed. Quote the correlation id if it continues.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}Retry-After and retry.Example error body
{
"code": "service_unavailable",
"message": "The API is briefly unavailable. Retry after the interval in Retry-After.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}Messages
/orders/{order_id}/messagesRead the message thread on an order
Returns the messages on the order that the lender is party to, ordered by
created_at ascending, with their attachments. Internal notes between the
company and the appraiser are not included: you see the thread the lender
sees in the portal.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
page | query | integer | The page to return, starting at 1. |
per_page | query | integer | How many items to return per page, from 1 to 100. |
Responses
{
"data": [
{
"id": "msg_7SG1T4ZXUE07",
"order_id": "ord_9TBK4C2QFA7M",
"recipient": "manager",
"subject": "Access arrangements",
"body": "The listing agent will meet the appraiser on site.",
"author": {
"type": "lender",
"name": "Example Mortgage Group"
},
"attachments": [],
"created_at": "2026-09-18T15:10:00Z"
},
{
"id": "msg_8TH2U5AYVF18",
"order_id": "ord_9TBK4C2QFA7M",
"recipient": "lender",
"subject": "Access arrangements",
"body": "Understood. The appraiser will call the agent to confirm.",
"author": {
"type": "manager",
"name": "Order Desk"
},
"attachments": [],
"created_at": "2026-09-18T16:02:00Z"
}
],
"page": 1,
"per_page": 25,
"total": 2,
"total_pages": 1
}Example error body
{
"code": "token_expired",
"message": "The access token has expired.",
"correlation_id": "req_01J9Z41P0R3T6W9Y2B5D8F1H"
}Example error body
{
"code": "action_not_permitted_for_client",
"message": "This client is not permitted to cancel orders.",
"correlation_id": "req_01J9Z42R2T5W8Y1B4D7F0H3K"
}Example error body
{
"code": "not_found",
"message": "No order with that id.",
"correlation_id": "req_01J9Z43T4W7Y0B3D6F9H2K5M"
}Retry-After and retry.Example error body
{
"code": "rate_limited",
"message": "Too many requests. Retry after 30 seconds.",
"correlation_id": "req_01J9Z48F4H7K0M3P6R9T2W5Y"
}Idempotency-Key. For a write that takes no key, such as a message, an
upload or a revision request, read the order first rather than sending it
again. Quote the correlation_id to our integrations team.Example error body
{
"code": "internal_error",
"message": "The request could not be completed. Quote the correlation id if it continues.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}Retry-After and retry.Example error body
{
"code": "service_unavailable",
"message": "The API is briefly unavailable. Retry after the interval in Retry-After.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}/orders/{order_id}/messagesPost a message on an order
Sends a message to the appraisal management company, or to the appraiser
when the company allows direct contact. recipient must be manager or
appraiser; a company that keeps appraiser contact in its own hands
refuses appraiser with 422 and code recipient_not_allowed.
Attach a document by uploading it first and quoting its id, or send the message on its own.
Request bodyrequired
Content type: application/json
| Field | Type | Description |
|---|---|---|
recipientrequired | string enum | Who the message is for. A company that keeps appraiser contact in its
own hands refuses appraiser with 422 and code
recipient_not_allowed.One of: manager, appraiser |
subject | string or null | |
bodyrequired | string | |
document_ids | array of string | Documents already uploaded to this order to attach. |
Example request
{
"recipient": "manager",
"subject": "Access arrangements",
"body": "The listing agent will meet the appraiser on site.",
"document_ids": []
}Responses
{
"id": "msg_7SG1T4ZXUE07",
"order_id": "ord_9TBK4C2QFA7M",
"recipient": "manager",
"subject": "Access arrangements",
"body": "The listing agent will meet the appraiser on site.",
"author": {
"type": "lender",
"name": "Example Mortgage Group"
},
"attachments": [],
"created_at": "2026-09-18T15:10:00Z"
}details names each field at fault.Example error body
{
"code": "validation_failed",
"message": "The request could not be processed. See details.",
"details": [
{
"field": "property.postal_code",
"code": "required",
"value": null,
"message": "A postal code is required."
},
{
"field": "loan.purpose",
"code": "invalid_value",
"value": "cash_out",
"message": "Must be one of: construction_only, construction_to_permanent, mortgage_modification, other, purchase, refinance."
}
],
"correlation_id": "req_01J9Z40M8P1R4T7W0Y3B6D9F"
}Example error body
{
"code": "token_expired",
"message": "The access token has expired.",
"correlation_id": "req_01J9Z41P0R3T6W9Y2B5D8F1H"
}Example error body
{
"code": "action_not_permitted_for_client",
"message": "This client is not permitted to cancel orders.",
"correlation_id": "req_01J9Z42R2T5W8Y1B4D7F0H3K"
}Example error body
{
"code": "not_found",
"message": "No order with that id.",
"correlation_id": "req_01J9Z43T4W7Y0B3D6F9H2K5M"
}Example error body
{
"code": "action_not_allowed_in_status",
"message": "A closed order cannot be amended.",
"current_status": "cancelled",
"details": [
{
"field": "status",
"code": "current_status",
"value": "cancelled",
"message": "The order has been cancelled."
}
],
"correlation_id": "req_01J9Z44W6Y9B2D5F8H1K4M7P"
}Content-Type is not supported. JSON endpoints require
application/json; the upload endpoint requires multipart/form-data
with a file of an accepted type.Example error body
{
"code": "unsupported_media_type",
"message": "Send application/json.",
"correlation_id": "req_01J9Z46B0D3F6H9K2M5P8R1T"
}Example error body
{
"code": "semantic_validation_failed",
"message": "The loan type does not apply to this order type.",
"details": [
{
"field": "loan_type_code",
"code": "not_applicable",
"value": "va",
"message": "That loan type is not available on order type SFR-1004-FHA. Read GET /order-types for the loan types the product accepts."
}
],
"correlation_id": "req_01J9Z47D2F5H8K1M4P7R0T3W"
}Retry-After and retry.Example error body
{
"code": "rate_limited",
"message": "Too many requests. Retry after 30 seconds.",
"correlation_id": "req_01J9Z48F4H7K0M3P6R9T2W5Y"
}Idempotency-Key. For a write that takes no key, such as a message, an
upload or a revision request, read the order first rather than sending it
again. Quote the correlation_id to our integrations team.Example error body
{
"code": "internal_error",
"message": "The request could not be completed. Quote the correlation id if it continues.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}Retry-After and retry.Example error body
{
"code": "service_unavailable",
"message": "The API is briefly unavailable. Retry after the interval in Retry-After.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}Documents
/orders/{order_id}/documentsList the documents on an order
Returns every document on the order that the lender may see, ordered by
created_at descending with id as the tie break, as summaries without a
download link. Ask for a link one document at a
time with GET /documents/{document_id}, so that links are short lived
and are only minted when you are about to use them.
Which documents arrive depends on the product's report format. A product on the prior report standard delivers the report as a PDF plus the report data as an XML file. A product on the current standard delivers the report as a PDF plus the report data as a package in ZIP form. In both cases the invoice, the certificates and any other delivery document are separate files: the package never contains them.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
page | query | integer | The page to return, starting at 1. |
per_page | query | integer | How many items to return per page, from 1 to 100. |
kind | query | string enum | Return only documents of this kind. |
Responses
{
"data": [
{
"id": "doc_3XH8M1PLQW60",
"kind": "report_pdf",
"filename": "report_2026-1043.pdf",
"content_type": "application/pdf",
"size_bytes": 2841773,
"created_at": "2026-09-29T18:12:44Z"
},
{
"id": "doc_5RJ2N7VKTB41",
"kind": "report_data",
"filename": "report_2026-1043.zip",
"content_type": "application/zip",
"size_bytes": 1044210,
"created_at": "2026-09-29T18:12:44Z"
},
{
"id": "doc_8QL4P9WMYC72",
"kind": "invoice",
"filename": "invoice_2026-1043.pdf",
"content_type": "application/pdf",
"size_bytes": 88120,
"created_at": "2026-09-29T18:12:45Z"
}
],
"page": 1,
"per_page": 25,
"total": 3,
"total_pages": 1
}Example error body
{
"code": "token_expired",
"message": "The access token has expired.",
"correlation_id": "req_01J9Z41P0R3T6W9Y2B5D8F1H"
}Example error body
{
"code": "action_not_permitted_for_client",
"message": "This client is not permitted to cancel orders.",
"correlation_id": "req_01J9Z42R2T5W8Y1B4D7F0H3K"
}Example error body
{
"code": "not_found",
"message": "No order with that id.",
"correlation_id": "req_01J9Z43T4W7Y0B3D6F9H2K5M"
}Retry-After and retry.Example error body
{
"code": "rate_limited",
"message": "Too many requests. Retry after 30 seconds.",
"correlation_id": "req_01J9Z48F4H7K0M3P6R9T2W5Y"
}Idempotency-Key. For a write that takes no key, such as a message, an
upload or a revision request, read the order first rather than sending it
again. Quote the correlation_id to our integrations team.Example error body
{
"code": "internal_error",
"message": "The request could not be completed. Quote the correlation id if it continues.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}Retry-After and retry.Example error body
{
"code": "service_unavailable",
"message": "The API is briefly unavailable. Retry after the interval in Retry-After.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}/orders/{order_id}/documentsUpload a supporting document
Uploads a document to an open order: a purchase and sale contract, an engagement letter, comparable sales for a reconsideration, or anything else the appraiser needs.
A document you upload is visible to the appraisal management company and
to the assigned appraiser. Send purpose to say what it is:
engagement_letter, sales_contract, prior_report or other.
Send multipart/form-data with a file part and a kind part. The limit
is 25 MB per file; a larger file is refused with 413. Accepted media types
are PDF, JPEG, PNG, TIFF, ZIP, plain text, XML, and the common office
document types; anything else is refused with 415. kind must be
supporting on an upload: a report, a report data file, an invoice or a
certificate is produced by the appraisal management company, never uploaded by a lender.
Request bodyrequired
Content type: multipart/form-data
| Field | Type | Description |
|---|---|---|
filerequired | string (binary) | The file. Up to 25 MB. |
kindrequired | string | Only supporting may be uploaded by a lender. |
purpose | string enum | What a document you upload is for. Optional; other is assumed when you
leave it out.One of: engagement_letter, sales_contract, prior_report, other |
description | string | What the file is, for the appraiser. |
Example request
{
"file": "(the bytes of purchase_and_sale.pdf)",
"kind": "supporting",
"purpose": "sales_contract",
"description": "Purchase and sale contract"
}Responses
{
"id": "doc_2KM7Q0VZTC93",
"kind": "supporting",
"filename": "purchase_and_sale.pdf",
"content_type": "application/pdf",
"size_bytes": 412998,
"created_at": "2026-09-17T14:40:11Z"
}details names each field at fault.Example error body
{
"code": "validation_failed",
"message": "The request could not be processed. See details.",
"details": [
{
"field": "property.postal_code",
"code": "required",
"value": null,
"message": "A postal code is required."
},
{
"field": "loan.purpose",
"code": "invalid_value",
"value": "cash_out",
"message": "Must be one of: construction_only, construction_to_permanent, mortgage_modification, other, purchase, refinance."
}
],
"correlation_id": "req_01J9Z40M8P1R4T7W0Y3B6D9F"
}Example error body
{
"code": "token_expired",
"message": "The access token has expired.",
"correlation_id": "req_01J9Z41P0R3T6W9Y2B5D8F1H"
}Example error body
{
"code": "action_not_permitted_for_client",
"message": "This client is not permitted to cancel orders.",
"correlation_id": "req_01J9Z42R2T5W8Y1B4D7F0H3K"
}Example error body
{
"code": "not_found",
"message": "No order with that id.",
"correlation_id": "req_01J9Z43T4W7Y0B3D6F9H2K5M"
}Example error body
{
"code": "action_not_allowed_in_status",
"message": "A closed order cannot be amended.",
"current_status": "cancelled",
"details": [
{
"field": "status",
"code": "current_status",
"value": "cancelled",
"message": "The order has been cancelled."
}
],
"correlation_id": "req_01J9Z44W6Y9B2D5F8H1K4M7P"
}Example error body
{
"code": "payload_too_large",
"message": "The file is larger than the 25 MB limit.",
"correlation_id": "req_01J9Z45Y8B1D4F7H0K3M6P9R"
}Content-Type is not supported. JSON endpoints require
application/json; the upload endpoint requires multipart/form-data
with a file of an accepted type.Example error body
{
"code": "unsupported_media_type",
"message": "Send application/json.",
"correlation_id": "req_01J9Z46B0D3F6H9K2M5P8R1T"
}Example error body
{
"code": "semantic_validation_failed",
"message": "The loan type does not apply to this order type.",
"details": [
{
"field": "loan_type_code",
"code": "not_applicable",
"value": "va",
"message": "That loan type is not available on order type SFR-1004-FHA. Read GET /order-types for the loan types the product accepts."
}
],
"correlation_id": "req_01J9Z47D2F5H8K1M4P7R0T3W"
}Retry-After and retry.Example error body
{
"code": "rate_limited",
"message": "Too many requests. Retry after 30 seconds.",
"correlation_id": "req_01J9Z48F4H7K0M3P6R9T2W5Y"
}Idempotency-Key. For a write that takes no key, such as a message, an
upload or a revision request, read the order first rather than sending it
again. Quote the correlation_id to our integrations team.Example error body
{
"code": "internal_error",
"message": "The request could not be completed. Quote the correlation id if it continues.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}Retry-After and retry.Example error body
{
"code": "service_unavailable",
"message": "The API is briefly unavailable. Retry after the interval in Retry-After.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}/documents/{document_id}Get a document and a link to download it
Returns the document's details and a signed download link that is valid
for five minutes and may be used more than once inside that window. Follow
the link with a plain GET and no credential of ours: the signature in the
link is the authorization. The expires value in the link is expires_at
in Unix seconds. Fetch a fresh link when one expires rather than storing
links.
A document you are not entitled to see returns 404, not 403, so that ids cannot be probed.
Responses
{
"id": "doc_5RJ2N7VKTB41",
"order_id": "ord_9TBK4C2QFA7M",
"kind": "report_data",
"filename": "report_2026-1043.zip",
"content_type": "application/zip",
"size_bytes": 1044210,
"created_at": "2026-09-29T18:12:44Z",
"download": {
"url": "https://api.appraisalhost.com/v1/download/doc_5RJ2N7VKTB41?expires=1790705864&signature=4f1c8e2b9a7d5c3f6e0b8a2d4c6f1e9b",
"expires_at": "2026-09-29T18:17:44Z"
}
}Example error body
{
"code": "token_expired",
"message": "The access token has expired.",
"correlation_id": "req_01J9Z41P0R3T6W9Y2B5D8F1H"
}Example error body
{
"code": "action_not_permitted_for_client",
"message": "This client is not permitted to cancel orders.",
"correlation_id": "req_01J9Z42R2T5W8Y1B4D7F0H3K"
}Example error body
{
"code": "not_found",
"message": "No order with that id.",
"correlation_id": "req_01J9Z43T4W7Y0B3D6F9H2K5M"
}Retry-After and retry.Example error body
{
"code": "rate_limited",
"message": "Too many requests. Retry after 30 seconds.",
"correlation_id": "req_01J9Z48F4H7K0M3P6R9T2W5Y"
}Idempotency-Key. For a write that takes no key, such as a message, an
upload or a revision request, read the order first rather than sending it
again. Quote the correlation_id to our integrations team.Example error body
{
"code": "internal_error",
"message": "The request could not be completed. Quote the correlation id if it continues.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}Retry-After and retry.Example error body
{
"code": "service_unavailable",
"message": "The API is briefly unavailable. Retry after the interval in Retry-After.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}Events
/eventsRead your event feed
Returns the events we raised for your client, ordered by created_at
ascending, which is also event id order, each with its webhook delivery
state. This is the catch-up feed: if your endpoint was
down, read forward from the last event id you processed and you will miss
nothing.
This endpoint uses a cursor rather than page numbers. Pass the last id you
processed as after, and keep reading while next_cursor is not null.
Events are retained for 30 days.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
after | query | string | Return events after this event id. Omit to start at the oldest retained event. |
type | query | string | One or more event types, comma separated. |
order_id | query | string | Return only events for this order. |
delivery_status | query | string enum | Return only events in this delivery state. |
per_page | query | integer | How many items to return per page, from 1 to 100. |
Responses
{
"data": [
{
"id": "evt_01M2T9W27R459H4DHVZGW4WNSS",
"type": "order.status_changed",
"created_at": "2026-09-18T13:04:11Z",
"order_id": "ord_9TBK4C2QFA7M",
"data": {
"order_id": "ord_9TBK4C2QFA7M",
"order_number": "2026-1043",
"status": {
"code": "appraiser_assigned",
"label": "Appraiser Assigned",
"changed_at": "2026-09-18T13:04:11Z"
},
"previous_status": {
"code": "new",
"label": "New Order"
}
},
"delivery": {
"status": "delivered",
"attempts": 1,
"last_attempt_at": "2026-09-18T13:04:13Z",
"next_attempt_at": null,
"last_response_status": 200
}
},
{
"id": "evt_01M3Q5WZA8V0AB3B4S4B8E3XC5",
"type": "order.completed",
"created_at": "2026-09-29T18:12:45Z",
"order_id": "ord_9TBK4C2QFA7M",
"data": {
"order_id": "ord_9TBK4C2QFA7M",
"order_number": "2026-1043",
"report_format": "uad_3_6",
"documents": [
{
"id": "doc_3XH8M1PLQW60",
"kind": "report_pdf",
"filename": "report_2026-1043.pdf",
"content_type": "application/pdf",
"size_bytes": 2841773,
"created_at": "2026-09-29T18:12:44Z"
},
{
"id": "doc_5RJ2N7VKTB41",
"kind": "report_data",
"filename": "report_2026-1043.zip",
"content_type": "application/zip",
"size_bytes": 1044210,
"created_at": "2026-09-29T18:12:44Z"
},
{
"id": "doc_8QL4P9WMYC72",
"kind": "invoice",
"filename": "invoice_2026-1043.pdf",
"content_type": "application/pdf",
"size_bytes": 88120,
"created_at": "2026-09-29T18:12:45Z"
}
],
"completed_at": "2026-09-29T18:12:44Z"
},
"delivery": {
"status": "failed",
"attempts": 3,
"last_attempt_at": "2026-09-29T18:48:02Z",
"next_attempt_at": "2026-09-29T20:48:02Z",
"last_response_status": 502
}
}
],
"next_cursor": "evt_01M3Q5WZA8V0AB3B4S4B8E3XC5"
}details names each field at fault.Example error body
{
"code": "validation_failed",
"message": "The request could not be processed. See details.",
"details": [
{
"field": "property.postal_code",
"code": "required",
"value": null,
"message": "A postal code is required."
},
{
"field": "loan.purpose",
"code": "invalid_value",
"value": "cash_out",
"message": "Must be one of: construction_only, construction_to_permanent, mortgage_modification, other, purchase, refinance."
}
],
"correlation_id": "req_01J9Z40M8P1R4T7W0Y3B6D9F"
}Example error body
{
"code": "token_expired",
"message": "The access token has expired.",
"correlation_id": "req_01J9Z41P0R3T6W9Y2B5D8F1H"
}Example error body
{
"code": "action_not_permitted_for_client",
"message": "This client is not permitted to cancel orders.",
"correlation_id": "req_01J9Z42R2T5W8Y1B4D7F0H3K"
}Example error body
{
"code": "semantic_validation_failed",
"message": "The loan type does not apply to this order type.",
"details": [
{
"field": "loan_type_code",
"code": "not_applicable",
"value": "va",
"message": "That loan type is not available on order type SFR-1004-FHA. Read GET /order-types for the loan types the product accepts."
}
],
"correlation_id": "req_01J9Z47D2F5H8K1M4P7R0T3W"
}Retry-After and retry.Example error body
{
"code": "rate_limited",
"message": "Too many requests. Retry after 30 seconds.",
"correlation_id": "req_01J9Z48F4H7K0M3P6R9T2W5Y"
}Idempotency-Key. For a write that takes no key, such as a message, an
upload or a revision request, read the order first rather than sending it
again. Quote the correlation_id to our integrations team.Example error body
{
"code": "internal_error",
"message": "The request could not be completed. Quote the correlation id if it continues.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}Retry-After and retry.Example error body
{
"code": "service_unavailable",
"message": "The API is briefly unavailable. Retry after the interval in Retry-After.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}Webhook Configuration
/webhook/testSend yourself a signed test event
Delivers one signed specimen event of the type you name to your configured endpoint, and returns what your endpoint answered. Use it to prove your signature check, your timestamp tolerance and your ten second acknowledgement before you place an order.
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. It works in both environments, on the same terms: a
handler that sees test true verifies the signature, answers 2xx, and
stops, without storing the event or looking the order up. A client with
no webhook configured is refused with 404 and code
webhook_not_configured.
Request bodyrequired
Content type: application/json
| Field | Type | Description |
|---|---|---|
typerequired | string enum | The event catalog.One of: order.created, order.status_changed, order.assigned, order.on_hold, order.resumed, order.cancelled, order.completed, order.document_added, order.message_posted, order.revision_requested, order.revision_responded, order.due_date_changed, order.fee_changed |
Example request
{
"type": "order.status_changed"
}Responses
delivered for the outcome.{
"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,
"error": null,
"attempted_at": "2026-09-18T16:02:04Z"
}details names each field at fault.Example error body
{
"code": "validation_failed",
"message": "The request could not be processed. See details.",
"details": [
{
"field": "property.postal_code",
"code": "required",
"value": null,
"message": "A postal code is required."
},
{
"field": "loan.purpose",
"code": "invalid_value",
"value": "cash_out",
"message": "Must be one of: construction_only, construction_to_permanent, mortgage_modification, other, purchase, refinance."
}
],
"correlation_id": "req_01J9Z40M8P1R4T7W0Y3B6D9F"
}Example error body
{
"code": "token_expired",
"message": "The access token has expired.",
"correlation_id": "req_01J9Z41P0R3T6W9Y2B5D8F1H"
}Example error body
{
"code": "action_not_permitted_for_client",
"message": "This client is not permitted to cancel orders.",
"correlation_id": "req_01J9Z42R2T5W8Y1B4D7F0H3K"
}Example error body
{
"code": "webhook_not_configured",
"message": "No webhook endpoint has been configured for this client.",
"correlation_id": "req_01J9Z3K4R7T0W3Y6B9D2F5H8"
}Content-Type is not supported. JSON endpoints require
application/json; the upload endpoint requires multipart/form-data
with a file of an accepted type.Example error body
{
"code": "unsupported_media_type",
"message": "Send application/json.",
"correlation_id": "req_01J9Z46B0D3F6H9K2M5P8R1T"
}Example error body
{
"code": "semantic_validation_failed",
"message": "The loan type does not apply to this order type.",
"details": [
{
"field": "loan_type_code",
"code": "not_applicable",
"value": "va",
"message": "That loan type is not available on order type SFR-1004-FHA. Read GET /order-types for the loan types the product accepts."
}
],
"correlation_id": "req_01J9Z47D2F5H8K1M4P7R0T3W"
}Retry-After and retry.Example error body
{
"code": "rate_limited",
"message": "Too many requests. Retry after 30 seconds.",
"correlation_id": "req_01J9Z48F4H7K0M3P6R9T2W5Y"
}Idempotency-Key. For a write that takes no key, such as a message, an
upload or a revision request, read the order first rather than sending it
again. Quote the correlation_id to our integrations team.Example error body
{
"code": "internal_error",
"message": "The request could not be completed. Quote the correlation id if it continues.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}Retry-After and retry.Example error body
{
"code": "service_unavailable",
"message": "The API is briefly unavailable. Retry after the interval in Retry-After.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}/webhookRead your webhook configuration
Returns the endpoint we deliver your events to, which event types you are subscribed to, and when the signing secret was last rotated. The secret itself is never returned.
Responses
{
"url": "https://los.example.com/hooks/appraisal-host",
"enabled": true,
"events": [
"*"
],
"secret_set": true,
"secret_rotated_at": "2026-09-15T09:00:00Z",
"updated_at": "2026-09-15T09:00:00Z"
}Example error body
{
"code": "token_expired",
"message": "The access token has expired.",
"correlation_id": "req_01J9Z41P0R3T6W9Y2B5D8F1H"
}Example error body
{
"code": "action_not_permitted_for_client",
"message": "This client is not permitted to cancel orders.",
"correlation_id": "req_01J9Z42R2T5W8Y1B4D7F0H3K"
}Example error body
{
"code": "webhook_not_configured",
"message": "No webhook endpoint has been configured for this client.",
"correlation_id": "req_01J9Z3K4R7T0W3Y6B9D2F5H8"
}Retry-After and retry.Example error body
{
"code": "rate_limited",
"message": "Too many requests. Retry after 30 seconds.",
"correlation_id": "req_01J9Z48F4H7K0M3P6R9T2W5Y"
}Idempotency-Key. For a write that takes no key, such as a message, an
upload or a revision request, read the order first rather than sending it
again. Quote the correlation_id to our integrations team.Example error body
{
"code": "internal_error",
"message": "The request could not be completed. Quote the correlation id if it continues.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}Retry-After and retry.Example error body
{
"code": "service_unavailable",
"message": "The API is briefly unavailable. Retry after the interval in Retry-After.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}/webhookSet or update your webhook configuration
Sets the endpoint we deliver your events to. The URL must be HTTPS and must answer a POST with a 2xx within 10 seconds.
This call replaces the fields you send and leaves the others as they are.
Omitting events keeps your current subscription; omitting secret keeps
your current secret, which this call never clears. Send
"enabled": false to stop delivery without losing your configuration.
Send secret to set or rotate the signing secret. Use at least 32
characters of random text. We store it in a form we can sign with and
never display it again, so keep your own copy. One secret is in force at a
time, and every attempt is signed with the secret in force when that
attempt is made, so a retry sent after a rotation carries the new secret.
Change both sides together, or accept either signature for a short window.
Send events to subscribe to a subset of event types, or ["*"] for all
of them. Unsubscribed events are still raised and still readable at
GET /events; we simply do not deliver them.
The appraisal management company can also set this endpoint for you from its own screens. The last write wins, whichever side made it.
Request bodyrequired
Content type: application/json
| Field | Type | Description |
|---|---|---|
urlrequired | string (uri) | An HTTPS URL that answers a POST with a 2xx within 10 seconds. |
enabled | boolean | Send false to stop delivery without losing your configuration. |
events | array of string | Event types to subscribe to, or ["*"] for all of them. Leave it out
to keep your current subscription. |
secret | string | Set or rotate the signing secret. At least 32 characters of random text. Never returned, and never cleared by this call: leave it out to keep the secret you have. |
Example request
{
"url": "https://los.example.com/hooks/appraisal-host",
"enabled": true,
"events": [
"order.status_changed",
"order.completed",
"order.document_added"
],
"secret": "example_webhook_secret_replace_this_with_32_random_characters"
}Responses
{
"url": "https://los.example.com/hooks/appraisal-host",
"enabled": true,
"events": [
"order.status_changed",
"order.completed",
"order.document_added"
],
"secret_set": true,
"secret_rotated_at": "2026-09-17T14:45:00Z",
"updated_at": "2026-09-17T14:45:00Z"
}details names each field at fault.Example error body
{
"code": "validation_failed",
"message": "The request could not be processed. See details.",
"details": [
{
"field": "property.postal_code",
"code": "required",
"value": null,
"message": "A postal code is required."
},
{
"field": "loan.purpose",
"code": "invalid_value",
"value": "cash_out",
"message": "Must be one of: construction_only, construction_to_permanent, mortgage_modification, other, purchase, refinance."
}
],
"correlation_id": "req_01J9Z40M8P1R4T7W0Y3B6D9F"
}Example error body
{
"code": "token_expired",
"message": "The access token has expired.",
"correlation_id": "req_01J9Z41P0R3T6W9Y2B5D8F1H"
}Example error body
{
"code": "action_not_permitted_for_client",
"message": "This client is not permitted to cancel orders.",
"correlation_id": "req_01J9Z42R2T5W8Y1B4D7F0H3K"
}Content-Type is not supported. JSON endpoints require
application/json; the upload endpoint requires multipart/form-data
with a file of an accepted type.Example error body
{
"code": "unsupported_media_type",
"message": "Send application/json.",
"correlation_id": "req_01J9Z46B0D3F6H9K2M5P8R1T"
}Example error body
{
"code": "semantic_validation_failed",
"message": "The loan type does not apply to this order type.",
"details": [
{
"field": "loan_type_code",
"code": "not_applicable",
"value": "va",
"message": "That loan type is not available on order type SFR-1004-FHA. Read GET /order-types for the loan types the product accepts."
}
],
"correlation_id": "req_01J9Z47D2F5H8K1M4P7R0T3W"
}Retry-After and retry.Example error body
{
"code": "rate_limited",
"message": "Too many requests. Retry after 30 seconds.",
"correlation_id": "req_01J9Z48F4H7K0M3P6R9T2W5Y"
}Idempotency-Key. For a write that takes no key, such as a message, an
upload or a revision request, read the order first rather than sending it
again. Quote the correlation_id to our integrations team.Example error body
{
"code": "internal_error",
"message": "The request could not be completed. Quote the correlation id if it continues.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}Retry-After and retry.Example error body
{
"code": "service_unavailable",
"message": "The API is briefly unavailable. Retry after the interval in Retry-After.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}Sandbox
/sandbox/orders/{order_id}/advanceMove a sandbox order to another status
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.
Three rules govern it.
- It exists in the sandbox environment only. The same path in production returns 404.
- 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 reachpending_review,revision_requested,reconsideration_requested,on_hold,off_hold,cancelledorreactivatedthis way: those are produced byPOST /orders, byPOST /orders/{order_id}/revision-requests, and byhold,resumeandcancel, which work in the sandbox exactly as they do in production. A move the table does not list is refused with 409 and codeaction_not_allowed_in_status, with the order's current status incurrent_statusand the status you asked for indetails[0].value. - It fires the same notifications production fires.
| Current status | to_status you may name |
|---|---|
pending_review | new |
new | appraiser_assigned, appraiser_accepted, borrower_contacted, left_message_for_borrower, appointment_scheduled, awaiting_review, report_rejected_for_correction, report_complete |
appraiser_assigned | appraiser_accepted, borrower_contacted, left_message_for_borrower, appointment_scheduled, awaiting_review, report_rejected_for_correction, report_complete |
appraiser_accepted | borrower_contacted, left_message_for_borrower, appointment_scheduled, awaiting_review, report_rejected_for_correction, report_complete |
borrower_contacted | left_message_for_borrower, appointment_scheduled, awaiting_review, report_rejected_for_correction, report_complete |
left_message_for_borrower | borrower_contacted, appointment_scheduled, awaiting_review, report_rejected_for_correction, report_complete |
appointment_scheduled | awaiting_review, report_rejected_for_correction, report_complete |
awaiting_review | report_rejected_for_correction, report_complete |
report_rejected_for_correction | awaiting_review, report_complete |
report_complete | Nothing. Open a correction or a reconsideration first, which moves the order to revision_requested or reconsideration_requested. |
revision_requested | revised_report_complete |
reconsideration_requested | revised_report_complete |
revised_report_complete | Nothing. Open another correction first. |
on_hold, cancelled | Nothing. 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.
Drive your test suite from this call: place an order, advance it through assignment, appointment, review and delivery, and assert on what your listener received.
Request bodyrequired
Content type: application/json
| Field | Type | Description |
|---|---|---|
to_statusrequired | string enum | The status to move the order to. These are the statuses this call can
set. pending_review is set by order creation, revision_requested
and reconsideration_requested by
POST /orders/{order_id}/revision-requests, and on_hold,
off_hold, cancelled and reactivated by hold, resume and
cancel, so none of them can be named here. Which of these is legal
from the order's current status is in the transition table on the
advance operation.One of: new, appraiser_assigned, appraiser_accepted, borrower_contacted, left_message_for_borrower, appointment_scheduled, awaiting_review, report_rejected_for_correction, report_complete, revised_report_complete |
note | string or null | Optional text to carry on the status, as a company would enter it. |
Example request
{
"to_status": "appraiser_assigned"
}Responses
{
"id": "ord_9TBK4C2QFA7M",
"order_number": "2026-1043",
"lender_reference": "LN-2026-88421",
"status": {
"code": "pending_review",
"label": "Appraiser Assigned",
"changed_at": "2026-09-17T14:30:00Z"
},
"order_type": {
"code": "SFR-1004-36",
"name": "Single Family Residential, current report standard",
"report_format": "uad_2_6",
"appraiser_certification": "none"
},
"loan": {
"purpose": "construction_only",
"purpose_other": "string",
"number": "88421",
"client": "string",
"investor": "string",
"agency_case_number": "string",
"fha_case_number": "string",
"purchase_price": "415000.00",
"currency": "USD",
"loan_type": {
"code": "conventional",
"name": "Conventional"
},
"add_ons": [
{
"code": "conventional",
"name": "Conventional"
}
]
},
"property": {
"address": {
"street": "100 Example Avenue",
"unit": "Unit 2",
"city": "Springfield",
"state": "IL",
"postal_code": "62701",
"county": "Sangamon"
},
"type": "church",
"occupancy": "investment_property",
"has_adu": true
},
"borrowers": [
{
"first_name": "Sample",
"last_name": "Borrower",
"address": {},
"receives_report": false,
"receives_status_updates": false,
"role": "borrower",
"contacts": [
{}
]
}
],
"parties": {
"real_estate_agent": {
"first_name": "string",
"last_name": "string",
"company": "string",
"contacts": [
{}
]
},
"additional_contacts": [
{
"purpose": "report",
"name": "string",
"email": "processing@example.com"
}
]
},
"notes": [
{
"type": "order",
"text": "string"
}
],
"flags": {
"rush": false,
"complex": false,
"rural": false,
"priority": false,
"certified_appraiser_required": false
},
"appraiser_instructions": "string",
"appraiser": {
"name": "J. Marsh"
},
"dates": {
"created_at": "2026-09-17T14:30:00Z",
"updated_at": "2026-09-17T14:30:00Z",
"due_date": "2026-09-30",
"appointment_at": "2026-09-17T14:30:00Z",
"completed_at": "2026-09-17T14:30:00Z"
},
"fees": {
"appraisal_fee": "525.00",
"currency": "USD"
},
"documents": [
{
"id": "doc_5RJ2N7VKTB41",
"kind": "report_pdf",
"filename": "report_2026-1043.zip",
"content_type": "application/zip",
"size_bytes": 1044210,
"description": "string",
"created_at": "2026-09-17T14:30:00Z"
}
]
}details names each field at fault.Example error body
{
"code": "validation_failed",
"message": "The request could not be processed. See details.",
"details": [
{
"field": "property.postal_code",
"code": "required",
"value": null,
"message": "A postal code is required."
},
{
"field": "loan.purpose",
"code": "invalid_value",
"value": "cash_out",
"message": "Must be one of: construction_only, construction_to_permanent, mortgage_modification, other, purchase, refinance."
}
],
"correlation_id": "req_01J9Z40M8P1R4T7W0Y3B6D9F"
}Example error body
{
"code": "token_expired",
"message": "The access token has expired.",
"correlation_id": "req_01J9Z41P0R3T6W9Y2B5D8F1H"
}Example error body
{
"code": "action_not_permitted_for_client",
"message": "This client is not permitted to cancel orders.",
"correlation_id": "req_01J9Z42R2T5W8Y1B4D7F0H3K"
}Example error body
{
"code": "not_found",
"message": "No order with that id in this environment.",
"correlation_id": "req_01J9Z3K4R7T0W3Y6B9D2F5H8"
}Example error body
{
"code": "action_not_allowed_in_status",
"message": "An order cannot be moved backwards.",
"current_status": "report_complete",
"details": [
{
"field": "to_status",
"code": "not_applicable",
"value": "appraiser_assigned",
"message": "The order is already at report_complete."
}
],
"correlation_id": "req_01J9Z3K4R7T0W3Y6B9D2F5H8"
}Content-Type is not supported. JSON endpoints require
application/json; the upload endpoint requires multipart/form-data
with a file of an accepted type.Example error body
{
"code": "unsupported_media_type",
"message": "Send application/json.",
"correlation_id": "req_01J9Z46B0D3F6H9K2M5P8R1T"
}Example error body
{
"code": "semantic_validation_failed",
"message": "The loan type does not apply to this order type.",
"details": [
{
"field": "loan_type_code",
"code": "not_applicable",
"value": "va",
"message": "That loan type is not available on order type SFR-1004-FHA. Read GET /order-types for the loan types the product accepts."
}
],
"correlation_id": "req_01J9Z47D2F5H8K1M4P7R0T3W"
}Retry-After and retry.Example error body
{
"code": "rate_limited",
"message": "Too many requests. Retry after 30 seconds.",
"correlation_id": "req_01J9Z48F4H7K0M3P6R9T2W5Y"
}Idempotency-Key. For a write that takes no key, such as a message, an
upload or a revision request, read the order first rather than sending it
again. Quote the correlation_id to our integrations team.Example error body
{
"code": "internal_error",
"message": "The request could not be completed. Quote the correlation id if it continues.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}Retry-After and retry.Example error body
{
"code": "service_unavailable",
"message": "The API is briefly unavailable. Retry after the interval in Retry-After.",
"correlation_id": "req_01J9Z49H6K9M2P5R8T1W4Y7B"
}Notifications
Each notification is an HTTPS POST to the address you configure. Verify the signature before acting on the payload.
order.createdAn order was created
Raised when an order is created for your lender account, including orders placed in the portal by the lender's own staff rather than through the API.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
X-AH-Signaturerequired | header | string | The signature over the delivery, as t=<unix seconds>,v1=<hex>. v1 is a
hex encoded HMAC-SHA256 of the string <t>.<raw request body> keyed with
your webhook secret. t is when we signed this attempt, not when the
event was raised: a retry hours later carries a fresh t and the original
created_at. Compare v1 with a constant time comparison, and reject a
delivery whose t is more than five minutes from your own clock. |
X-AH-Event-Idrequired | header | string | The event id, the same value as id in the body. Use it to make your handler idempotent. |
X-AH-Event-Typerequired | header | string | The event type, the same value as type in the body. Useful for routing before you parse. |
Payload
{
"id": "evt_01M2QWG9M8BSNHMTEF5XX0GB38",
"type": "order.created",
"created_at": "2026-09-17T14:32:05Z",
"api_version": "1.0.0",
"data": {
"order_id": "ord_9TBK4C2QFA7M",
"order_number": "2026-1043",
"lender_reference": "LN-2026-88421",
"order_type": {
"code": "SFR-1004-36",
"name": "Single Family Residential, current report standard",
"report_format": "uad_3_6",
"appraiser_certification": "none"
},
"status": {
"code": "new",
"label": "New Order",
"changed_at": "2026-09-17T14:32:05Z"
},
"due_date": "2026-10-02",
"created_at": "2026-09-17T14:32:05Z"
}
}order.status_changedAn order's status changed
Raised on every change to the status the lender sees. An order is always reported with the status the lender sees in the portal, in the same words.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
X-AH-Signaturerequired | header | string | The signature over the delivery, as t=<unix seconds>,v1=<hex>. v1 is a
hex encoded HMAC-SHA256 of the string <t>.<raw request body> keyed with
your webhook secret. t is when we signed this attempt, not when the
event was raised: a retry hours later carries a fresh t and the original
created_at. Compare v1 with a constant time comparison, and reject a
delivery whose t is more than five minutes from your own clock. |
X-AH-Event-Idrequired | header | string | The event id, the same value as id in the body. Use it to make your handler idempotent. |
X-AH-Event-Typerequired | header | string | The event type, the same value as type in the body. Useful for routing before you parse. |
Payload
{
"id": "evt_01M2T9W27R459H4DHVZGW4WNSS",
"type": "order.status_changed",
"created_at": "2026-09-18T13:04:11Z",
"api_version": "1.0.0",
"data": {
"order_id": "ord_9TBK4C2QFA7M",
"order_number": "2026-1043",
"status": {
"code": "appraiser_assigned",
"label": "Appraiser Assigned",
"changed_at": "2026-09-18T13:04:11Z"
},
"previous_status": {
"code": "new",
"label": "New Order"
},
"note": "Assigned to a certified appraiser covering Sangamon county."
}
}order.assignedAn appraiser was assigned
Raised when the appraisal management company assigns an appraiser. The
event always fires. appraiser carries the appraiser's display name where
the company shares the assigned appraiser with its lenders, and is null
where it does not.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
X-AH-Signaturerequired | header | string | The signature over the delivery, as t=<unix seconds>,v1=<hex>. v1 is a
hex encoded HMAC-SHA256 of the string <t>.<raw request body> keyed with
your webhook secret. t is when we signed this attempt, not when the
event was raised: a retry hours later carries a fresh t and the original
created_at. Compare v1 with a constant time comparison, and reject a
delivery whose t is more than five minutes from your own clock. |
X-AH-Event-Idrequired | header | string | The event id, the same value as id in the body. Use it to make your handler idempotent. |
X-AH-Event-Typerequired | header | string | The event type, the same value as type in the body. Useful for routing before you parse. |
Payload
{
"id": "evt_01M2T9W27RXJWVPHSK03CJAJQH",
"type": "order.assigned",
"created_at": "2026-09-18T13:04:11Z",
"api_version": "1.0.0",
"data": {
"order_id": "ord_9TBK4C2QFA7M",
"order_number": "2026-1043",
"appraiser": {
"name": "J. Marsh"
},
"assigned_at": "2026-09-18T13:04:11Z"
}
}order.on_holdAn order was placed on hold
Raised when an order is put on hold, whoever put it there.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
X-AH-Signaturerequired | header | string | The signature over the delivery, as t=<unix seconds>,v1=<hex>. v1 is a
hex encoded HMAC-SHA256 of the string <t>.<raw request body> keyed with
your webhook secret. t is when we signed this attempt, not when the
event was raised: a retry hours later carries a fresh t and the original
created_at. Compare v1 with a constant time comparison, and reject a
delivery whose t is more than five minutes from your own clock. |
X-AH-Event-Idrequired | header | string | The event id, the same value as id in the body. Use it to make your handler idempotent. |
X-AH-Event-Typerequired | header | string | The event type, the same value as type in the body. Useful for routing before you parse. |
Payload
{
"id": "evt_01M2WN9220WJX8W2ZDA9CMHHKM",
"type": "order.on_hold",
"created_at": "2026-09-19T11:02:00Z",
"api_version": "1.0.0",
"data": {
"order_id": "ord_9TBK4C2QFA7M",
"order_number": "2026-1043",
"status": {
"code": "on_hold",
"label": "On Hold",
"changed_at": "2026-09-19T11:02:00Z"
},
"reason": "Borrower is renegotiating the purchase price."
}
}order.resumedAn order resumed from hold
Raised when an order comes off hold and work restarts.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
X-AH-Signaturerequired | header | string | The signature over the delivery, as t=<unix seconds>,v1=<hex>. v1 is a
hex encoded HMAC-SHA256 of the string <t>.<raw request body> keyed with
your webhook secret. t is when we signed this attempt, not when the
event was raised: a retry hours later carries a fresh t and the original
created_at. Compare v1 with a constant time comparison, and reject a
delivery whose t is more than five minutes from your own clock. |
X-AH-Event-Idrequired | header | string | The event id, the same value as id in the body. Use it to make your handler idempotent. |
X-AH-Event-Typerequired | header | string | The event type, the same value as type in the body. Useful for routing before you parse. |
Payload
{
"id": "evt_01M344BJF0DA2RXN7VKXTHJWEG",
"type": "order.resumed",
"created_at": "2026-09-22T08:40:12Z",
"api_version": "1.0.0",
"data": {
"order_id": "ord_9TBK4C2QFA7M",
"order_number": "2026-1043",
"status": {
"code": "off_hold",
"label": "Off Hold",
"changed_at": "2026-09-22T08:40:12Z"
},
"reason": "Purchase price agreed, please proceed."
}
}order.cancelledAn order was cancelled
Raised when an order is cancelled, whoever cancelled it.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
X-AH-Signaturerequired | header | string | The signature over the delivery, as t=<unix seconds>,v1=<hex>. v1 is a
hex encoded HMAC-SHA256 of the string <t>.<raw request body> keyed with
your webhook secret. t is when we signed this attempt, not when the
event was raised: a retry hours later carries a fresh t and the original
created_at. Compare v1 with a constant time comparison, and reject a
delivery whose t is more than five minutes from your own clock. |
X-AH-Event-Idrequired | header | string | The event id, the same value as id in the body. Use it to make your handler idempotent. |
X-AH-Event-Typerequired | header | string | The event type, the same value as type in the body. Useful for routing before you parse. |
Payload
{
"id": "evt_01M2ZT0NARH2NGSGKRP6ZFPYN7",
"type": "order.cancelled",
"created_at": "2026-09-20T16:22:31Z",
"api_version": "1.0.0",
"data": {
"order_id": "ord_9TBK4C2QFA7M",
"order_number": "2026-1043",
"status": {
"code": "cancelled",
"label": "Order Cancelled",
"changed_at": "2026-09-20T16:22:31Z"
},
"reason": "Loan withdrawn by the borrower."
}
}order.completedA report was delivered
Raised when the report is delivered, and again when a revised report is
delivered. documents lists every file that came with the delivery, each
as a separate document. Fetch each one with
GET /documents/{document_id} to obtain a signed link.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
X-AH-Signaturerequired | header | string | The signature over the delivery, as t=<unix seconds>,v1=<hex>. v1 is a
hex encoded HMAC-SHA256 of the string <t>.<raw request body> keyed with
your webhook secret. t is when we signed this attempt, not when the
event was raised: a retry hours later carries a fresh t and the original
created_at. Compare v1 with a constant time comparison, and reject a
delivery whose t is more than five minutes from your own clock. |
X-AH-Event-Idrequired | header | string | The event id, the same value as id in the body. Use it to make your handler idempotent. |
X-AH-Event-Typerequired | header | string | The event type, the same value as type in the body. Useful for routing before you parse. |
Payload
{
"id": "evt_01M3Q5WZA8V0AB3B4S4B8E3XC5",
"type": "order.completed",
"created_at": "2026-09-29T18:12:45Z",
"api_version": "1.0.0",
"data": {
"order_id": "ord_9TBK4C2QFA7M",
"order_number": "2026-1043",
"status": {
"code": "report_complete",
"label": "Report Complete",
"changed_at": "2026-09-29T18:12:44Z"
},
"report_format": "uad_3_6",
"revision": false,
"completed_at": "2026-09-29T18:12:44Z",
"documents": [
{
"id": "doc_3XH8M1PLQW60",
"kind": "report_pdf",
"filename": "report_2026-1043.pdf",
"content_type": "application/pdf",
"size_bytes": 2841773,
"created_at": "2026-09-29T18:12:44Z"
},
{
"id": "doc_5RJ2N7VKTB41",
"kind": "report_data",
"filename": "report_2026-1043.zip",
"content_type": "application/zip",
"size_bytes": 1044210,
"created_at": "2026-09-29T18:12:44Z"
},
{
"id": "doc_8QL4P9WMYC72",
"kind": "invoice",
"filename": "invoice_2026-1043.pdf",
"content_type": "application/pdf",
"size_bytes": 88120,
"created_at": "2026-09-29T18:12:45Z"
}
]
}
}order.document_addedA document was added to an order
Raised when a document the lender may see is added to an order, including the files that arrive with a delivery and anything the company adds later.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
X-AH-Signaturerequired | header | string | The signature over the delivery, as t=<unix seconds>,v1=<hex>. v1 is a
hex encoded HMAC-SHA256 of the string <t>.<raw request body> keyed with
your webhook secret. t is when we signed this attempt, not when the
event was raised: a retry hours later carries a fresh t and the original
created_at. Compare v1 with a constant time comparison, and reject a
delivery whose t is more than five minutes from your own clock. |
X-AH-Event-Idrequired | header | string | The event id, the same value as id in the body. Use it to make your handler idempotent. |
X-AH-Event-Typerequired | header | string | The event type, the same value as type in the body. Useful for routing before you parse. |
Payload
{
"id": "evt_01M3Q5WZA8WNXQQRS6N3X84JWZ",
"type": "order.document_added",
"created_at": "2026-09-29T18:12:45Z",
"api_version": "1.0.0",
"data": {
"order_id": "ord_9TBK4C2QFA7M",
"order_number": "2026-1043",
"document": {
"id": "doc_8QL4P9WMYC72",
"kind": "invoice",
"filename": "invoice_2026-1043.pdf",
"content_type": "application/pdf",
"size_bytes": 88120,
"created_at": "2026-09-29T18:12:45Z"
}
}
}order.message_postedA message was posted on an order
Raised when a message the lender is party to is posted by the appraisal management company or the appraiser. Your own messages do not raise this event.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
X-AH-Signaturerequired | header | string | The signature over the delivery, as t=<unix seconds>,v1=<hex>. v1 is a
hex encoded HMAC-SHA256 of the string <t>.<raw request body> keyed with
your webhook secret. t is when we signed this attempt, not when the
event was raised: a retry hours later carries a fresh t and the original
created_at. Compare v1 with a constant time comparison, and reject a
delivery whose t is more than five minutes from your own clock. |
X-AH-Event-Idrequired | header | string | The event id, the same value as id in the body. Use it to make your handler idempotent. |
X-AH-Event-Typerequired | header | string | The event type, the same value as type in the body. Useful for routing before you parse. |
Payload
{
"id": "evt_01M2TM1N60M4HGM9QGTHVCDMA2",
"type": "order.message_posted",
"created_at": "2026-09-18T16:02:00Z",
"api_version": "1.0.0",
"data": {
"order_id": "ord_9TBK4C2QFA7M",
"order_number": "2026-1043",
"message": {
"id": "msg_8TH2U5AYVF18",
"order_id": "ord_9TBK4C2QFA7M",
"recipient": "lender",
"subject": "Access arrangements",
"body": "Understood. The appraiser will call the agent to confirm.",
"author": {
"type": "manager",
"name": "Order Desk"
},
"attachments": [],
"created_at": "2026-09-18T16:02:00Z"
}
}
}order.revision_requestedA revision request was opened
Raised when a correction or a reconsideration of value is opened on the order, whether through the API or in the portal.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
X-AH-Signaturerequired | header | string | The signature over the delivery, as t=<unix seconds>,v1=<hex>. v1 is a
hex encoded HMAC-SHA256 of the string <t>.<raw request body> keyed with
your webhook secret. t is when we signed this attempt, not when the
event was raised: a retry hours later carries a fresh t and the original
created_at. Compare v1 with a constant time comparison, and reject a
delivery whose t is more than five minutes from your own clock. |
X-AH-Event-Idrequired | header | string | The event id, the same value as id in the body. Use it to make your handler idempotent. |
X-AH-Event-Typerequired | header | string | The event type, the same value as type in the body. Useful for routing before you parse. |
Payload
{
"id": "evt_01M3RWBA6G2CGMPB7GYCEAG70Y",
"type": "order.revision_requested",
"created_at": "2026-09-30T10:04:18Z",
"api_version": "1.0.0",
"data": {
"order_id": "ord_9TBK4C2QFA7M",
"order_number": "2026-1043",
"revision_request": {
"id": "rr_6PD3K8YWQN25",
"order_id": "ord_9TBK4C2QFA7M",
"kind": "reconsideration_of_value",
"status": "submitted",
"reason": "Three closed sales within 0.4 miles support a higher value.",
"acknowledgements": {
"prior_appraisal_provided": false,
"comparable_sales_provided": true
},
"documents": [],
"responses": [],
"created_at": "2026-09-30T10:04:18Z",
"updated_at": "2026-09-30T10:04:18Z"
}
}
}order.revision_respondedA revision request was answered
Raised when the appraisal management company accepts, declines or comments on a revision request.
A revised report that follows arrives as order.completed with
revision set to true.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
X-AH-Signaturerequired | header | string | The signature over the delivery, as t=<unix seconds>,v1=<hex>. v1 is a
hex encoded HMAC-SHA256 of the string <t>.<raw request body> keyed with
your webhook secret. t is when we signed this attempt, not when the
event was raised: a retry hours later carries a fresh t and the original
created_at. Compare v1 with a constant time comparison, and reject a
delivery whose t is more than five minutes from your own clock. |
X-AH-Event-Idrequired | header | string | The event id, the same value as id in the body. Use it to make your handler idempotent. |
X-AH-Event-Typerequired | header | string | The event type, the same value as type in the body. Useful for routing before you parse. |
Payload
{
"id": "evt_01M3SFKTQ0PPQ3NCREDTYS1BKE",
"type": "order.revision_responded",
"created_at": "2026-09-30T15:41:00Z",
"api_version": "1.0.0",
"data": {
"order_id": "ord_9TBK4C2QFA7M",
"order_number": "2026-1043",
"revision_request_id": "rr_6PD3K8YWQN25",
"status": "accepted",
"response": {
"id": "msg_4NF9R2XWTD86",
"created_at": "2026-09-30T15:41:00Z",
"author": {
"type": "manager",
"name": "Order Desk"
},
"message": "Sent to the appraiser for review. Revised report expected within two business days."
}
}
}order.due_date_changedAn order's due date changed
Raised when the due date on the order changes, including when the appraisal management company accepts or adjusts a date you requested.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
X-AH-Signaturerequired | header | string | The signature over the delivery, as t=<unix seconds>,v1=<hex>. v1 is a
hex encoded HMAC-SHA256 of the string <t>.<raw request body> keyed with
your webhook secret. t is when we signed this attempt, not when the
event was raised: a retry hours later carries a fresh t and the original
created_at. Compare v1 with a constant time comparison, and reject a
delivery whose t is more than five minutes from your own clock. |
X-AH-Event-Idrequired | header | string | The event id, the same value as id in the body. Use it to make your handler idempotent. |
X-AH-Event-Typerequired | header | string | The event type, the same value as type in the body. Useful for routing before you parse. |
Payload
{
"id": "evt_01M2WFE9G0VF1S24AE8RTAH2ZC",
"type": "order.due_date_changed",
"created_at": "2026-09-19T09:20:00Z",
"api_version": "1.0.0",
"data": {
"order_id": "ord_9TBK4C2QFA7M",
"order_number": "2026-1043",
"due_date": "2026-10-06",
"previous_due_date": "2026-10-02",
"requested_by": "lender"
}
}order.fee_changedAn order's fee changed
Raised when the fee the lender is charged changes. The fee is read only through the API: fee negotiation happens between the appraisal management company and the lender, not over this interface.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
X-AH-Signaturerequired | header | string | The signature over the delivery, as t=<unix seconds>,v1=<hex>. v1 is a
hex encoded HMAC-SHA256 of the string <t>.<raw request body> keyed with
your webhook secret. t is when we signed this attempt, not when the
event was raised: a retry hours later carries a fresh t and the original
created_at. Compare v1 with a constant time comparison, and reject a
delivery whose t is more than five minutes from your own clock. |
X-AH-Event-Idrequired | header | string | The event id, the same value as id in the body. Use it to make your handler idempotent. |
X-AH-Event-Typerequired | header | string | The event type, the same value as type in the body. Useful for routing before you parse. |
Payload
{
"id": "evt_01M31Z3MA00XVKABD7905AR0R1",
"type": "order.fee_changed",
"created_at": "2026-09-21T12:30:00Z",
"api_version": "1.0.0",
"data": {
"order_id": "ord_9TBK4C2QFA7M",
"order_number": "2026-1043",
"appraisal_fee": "575.00",
"previous_appraisal_fee": "525.00",
"currency": "USD",
"reason": "Complex property, additional scope agreed with the lender."
}
}Objects
Every object the API sends or accepts, with its fields. Open one to read it.
Ping
| Field | Type | Description |
|---|---|---|
statusrequired | string | |
timerequired | string (date-time) | Our clock in UTC, useful when you verify signature timestamps. |
TokenRequest
| Field | Type | Description |
|---|---|---|
grant_typerequired | string | |
client_idrequired | string | The client id we issued. Always starts with cli_. |
client_secretrequired | string | The client secret we issued. Shown once, at creation. Store it in a secret manager. |
scope | string | Optional. The only scope in version 1 is lender, which is also the default. |
TokenResponse
| Field | Type | Description |
|---|---|---|
access_tokenrequired | string | The opaque token. Send it as Authorization: Bearer <access_token>. |
token_typerequired | string | |
expires_inrequired | integer | Seconds until the token expires, counted from this response. |
scoperequired | string |
Error
code is stable and safe to branch on. message is
plain text for a human and may be reworded. details names the fields at
fault when the failure is a validation failure.| Field | Type | Description |
|---|---|---|
coderequired | string | A stable machine readable code. |
messagerequired | string | A plain description of what went wrong. |
current_status | one of | The order's current status code. Present on every 409 that refuses an
action because of the status the order has reached, so that you can
branch without walking details. Absent on every other error. |
details | array of ErrorDetail | One entry per field at fault, when applicable. |
correlation_idrequired | string | The identifier for this request in our logs. Quote it when you contact us. |
ErrorDetail
| Field | Type | Description |
|---|---|---|
fieldrequired | string | A dotted path to the field, for example property.postal_code or borrowers.0.last_name. |
coderequired | string | A stable reason: required, invalid_value, too_long, not_applicable, not_found, current_status. |
value | string or null | The machine readable value at fault, when there is one: the value you
sent, or the order's current status code on a 409. Safe to branch on.
message never is. |
messagerequired | string | A plain explanation for a person. Never match on it. |
OAuthError
POST /oauth/token only, in the shape RFC 6749 defines.
Every other endpoint uses Error.| Field | Type | Description |
|---|---|---|
errorrequired | string enum | One of: invalid_request, invalid_client, invalid_grant, unauthorized_client, unsupported_grant_type, invalid_scope |
error_description | string or null | A plain explanation for a person. Never match on it. |
correlation_id | string or null | The identifier for this request in our logs. |
AccountParty
| Field | Type | Description |
|---|---|---|
idrequired | string | |
namerequired | string |
AccountRateLimit
| Field | Type | Description |
|---|---|---|
requests_per_minuterequired | integer |
Account
| Field | Type | Description |
|---|---|---|
client_idrequired | string | Your client id. Safe to log. |
environmentrequired | string enum | The environment this credential works in.One of: sandbox, production |
lenderrequired | object | The lender account orders placed with this credential belong to. |
companyrequired | object | The appraisal management company that holds the lender account. |
scopesrequired | array of string | The scopes the credential carries. Version 1 issues lender. |
rate_limitrequired | AccountRateLimit | The published limit for this client. |
SandboxAdvance
| Field | Type | Description |
|---|---|---|
to_statusrequired | string enum | The status to move the order to. These are the statuses this call can
set. pending_review is set by order creation, revision_requested
and reconsideration_requested by
POST /orders/{order_id}/revision-requests, and on_hold,
off_hold, cancelled and reactivated by hold, resume and
cancel, so none of them can be named here. Which of these is legal
from the order's current status is in the transition table on the
advance operation.One of: new, appraiser_assigned, appraiser_accepted, borrower_contacted, left_message_for_borrower, appointment_scheduled, awaiting_review, report_rejected_for_correction, report_complete, revised_report_complete |
note | string or null | Optional text to carry on the status, as a company would enter it. |
WebhookTestRequest
| Field | Type | Description |
|---|---|---|
typerequired | string enum | The event catalog.One of: order.created, order.status_changed, order.assigned, order.on_hold, order.resumed, order.cancelled, order.completed, order.document_added, order.message_posted, order.revision_requested, order.revision_responded, order.due_date_changed, order.fee_changed |
WebhookTestResult
test true and a synthetic order_id, always prefixed
ord_test_, which no real order in any environment ever carries. It is
not written to your feed, and no order changed.| Field | Type | Description |
|---|---|---|
event_idrequired | string | The id carried by the specimen event. It is not stored in your feed. |
typerequired | string enum | The event catalog.One of: order.created, order.status_changed, order.assigned, order.on_hold, order.resumed, order.cancelled, order.completed, order.document_added, order.message_posted, order.revision_requested, order.revision_responded, order.due_date_changed, order.fee_changed |
urlrequired | string (uri) | The endpoint we delivered to. |
deliveredrequired | boolean | True when your endpoint answered with a 2xx inside ten seconds. |
response_status | integer or null | The status your endpoint returned, when it returned one. |
response_time_ms | integer or null | |
error | string or null | What went wrong, when the delivery failed. |
attempted_atrequired | string (date-time) |
Pagination
| Field | Type | Description |
|---|---|---|
pagerequired | integer | |
per_pagerequired | integer | |
totalrequired | integer | How many items match in total. |
total_pagesrequired | integer |
ReportFormat
uad_2_6: the report arrives as a PDF, plusreport_dataas the MISMO 2.6 GSE appraisal XML, with the report PDF embedded as that standard defines.uad_3_6: the report arrives as a PDF, plusreport_dataas the UAD 3.6 delivery package, a ZIP produced by the appraiser's forms software to the GSE UAD 3.6 specification. The members of that package are defined by that specification. The package is delivered exactly as the forms software produced it, so whether a copy of the report PDF sits inside it is that software's doing;report_pdfis always delivered as its own file as well, and that is the copy to read.
One of: uad_2_6, uad_3_6
OrderStatusCode
pending_review: received, and with the appraisal management company for a look before it is placed. Nothing is wrong.new: received, not yet assigned.appraiser_assigned: an appraiser has the order.appraiser_accepted: the appraiser accepted the assignment.borrower_contacted: the appraiser has reached the contact.left_message_for_borrower: the appraiser left a message for the borrower or the broker.appointment_scheduled: an inspection appointment is set.awaiting_review: the report has been submitted and is in review before delivery.report_complete: the report has been delivered. Documents are available.report_rejected_for_correction: the report was sent back for correction before delivery.revision_requested: a correction has been requested on a delivered report.reconsideration_requested: a reconsideration of value has been requested.revised_report_complete: a revised report has been delivered.on_hold: work is paused.off_hold: work has resumed after a hold.cancelled: the order was cancelled.reactivated: a cancelled order was put back into production.
off_hold and reactivated are transitional: an order at either moves on
to its working status shortly afterwards, so read the order again rather
than treating one as a resting state.
Not every company uses every status, so treat this as the complete set of
what you may receive and never as a sequence you must see. A few labels
are ours rather than the company's, because the status they stand for is
internal to the company. Branch on code, display label, and store a
code you do not know rather than failing on it.One of: pending_review, new, appraiser_assigned, appraiser_accepted, borrower_contacted, left_message_for_borrower, appointment_scheduled, awaiting_review, report_complete, report_rejected_for_correction, revision_requested, reconsideration_requested, revised_report_complete, on_hold, off_hold, cancelled, reactivated
OrderStatus
| Field | Type | Description |
|---|---|---|
coderequired | string enum | The statuses this interface reports. An order is always reported with the
status the lender sees in the portal, in the same words.
off_hold and reactivated are transitional: an order at either moves on
to its working status shortly afterwards, so read the order again rather
than treating one as a resting state.
Not every company uses every status, so treat this as the complete set of
what you may receive and never as a sequence you must see. A few labels
are ours rather than the company's, because the status they stand for is
internal to the company. Branch on code, display label, and store a
code you do not know rather than failing on it.One of: pending_review, new, appraiser_assigned, appraiser_accepted, borrower_contacted, left_message_for_borrower, appointment_scheduled, awaiting_review, report_complete, report_rejected_for_correction, revision_requested, reconsideration_requested, revised_report_complete, on_hold, off_hold, cancelled, reactivated |
labelrequired | string | The wording the lender sees. An appraisal management company may reword its own labels, so
branch on code and display label. |
changed_atrequired | string (date-time) |
OrderStatusRef
| Field | Type | Description |
|---|---|---|
coderequired | string enum | The statuses this interface reports. An order is always reported with the
status the lender sees in the portal, in the same words.
off_hold and reactivated are transitional: an order at either moves on
to its working status shortly afterwards, so read the order again rather
than treating one as a resting state.
Not every company uses every status, so treat this as the complete set of
what you may receive and never as a sequence you must see. A few labels
are ours rather than the company's, because the status they stand for is
internal to the company. Branch on code, display label, and store a
code you do not know rather than failing on it.One of: pending_review, new, appraiser_assigned, appraiser_accepted, borrower_contacted, left_message_for_borrower, appointment_scheduled, awaiting_review, report_complete, report_rejected_for_correction, revision_requested, reconsideration_requested, revised_report_complete, on_hold, off_hold, cancelled, reactivated |
labelrequired | string |
LoanPurpose
other with loan.purpose_other when nothing else fits.One of: construction_only, construction_to_permanent, mortgage_modification, other, purchase, refinance
PropertyType
One of: church, commercial_non_residential, condominium, condominium_over_four_stories, cooperative, farm, home_and_business_combined, manufactured_mobile_home, mixed_use_residential, multifamily_more_than_four_units, other, single_family, townhouse, two_to_four_unit_property, vacant_land
Occupancy
One of: investment_property, primary_residence, second_home, vacant
ContactType
One of: phone, email
ContactRole
One of: home, cell, work, other
Contact
| Field | Type | Description |
|---|---|---|
typerequired | string enum | One of: phone, email |
rolerequired | object | Whose number or address this is. On an email address use home,
work or other. |
valuerequired | string | The phone number or the email address. Phone numbers are text:
include the country code, as in +1-217-555-0142, and read back what
you sent. |
Address
postal_code is required. city, state and county are filled in from
it when you leave them out, and the filled in values are returned on the
order. Where a postal code covers more than one place name we store the
postal service's preferred name. A postal code we cannot resolve is
refused with 422.| Field | Type | Description |
|---|---|---|
streetrequired | string | |
unit | string or null | |
city | string or null | |
state | string or null | The two letter state or territory code. |
postal_coderequired | string | |
county | string or null |
CatalogItem
| Field | Type | Description |
|---|---|---|
coderequired | string | Stable for this company. Send this value, not the name. |
namerequired | string | Display text. May be reworded. |
AppraiserCertification
none: no special certification.fha_required: only an FHA approved appraiser may take it, andloan.fha_case_numberis required on the order.fha_optional: an FHA approved appraiser may take it, and the case number is accepted but not required.usda: a USDA product, andloan.fha_case_numberis required on the order.
One of: none, fha_required, fha_optional, usda
OrderTypeRef
| Field | Type | Description |
|---|---|---|
coderequired | string | The product code. Codes belong to the appraisal management company and
are opaque: treat one as a string and read it from GET /order-types.
Some companies use numbers. A product appears only when the company has
enabled it for API ordering and given it a code. |
namerequired | string | |
report_formatrequired | string enum | The report standard a product is delivered in.
uad_2_6, uad_3_6 |
appraiser_certificationrequired | string enum | Which appraiser certification a product requires.
none, fha_required, fha_optional, usda |
OrderType
| Field | Type | Description |
|---|---|---|
coderequired | string | The product code. Codes belong to the appraisal management company and
are opaque: treat one as a string and read it from GET /order-types.
Some companies use numbers. A product appears only when the company has
enabled it for API ordering and given it a code. |
namerequired | string | |
report_formatrequired | string enum | The report standard a product is delivered in.
uad_2_6, uad_3_6 |
appraiser_certificationrequired | string enum | Which appraiser certification a product requires.
none, fha_required, fha_optional, usda |
description | string or null | The company's own description of the product, when it has set one. |
activerequired | boolean | False when the company has withdrawn the product. A withdrawn product cannot be ordered. |
loan_typesrequired | array of CatalogItem | The loan type tier that may be attached to this product. Empty for
a product that does not take one, which today means every product
other than those on the current report standard. When the list is
not empty, loan_type_code is required on create. |
add_onsrequired | array of CatalogItem | The add-ons that may be attached to this product. Add-ons are not
particular to one report standard: read this list on every
product rather than assuming which products carry them. Some
add-ons apply only when the property has an accessory dwelling
unit: pass has_adu=true to see those as well.
Some add-ons are quoted by the appraisal management company rather
than priced from a rate card. An order carrying one is placed with
fees.appraisal_fee null until the company quotes it, and
order.fee_changed tells you the price. |
loan_purposes | array of string enum | The loan purposes this product may be ordered for. An empty list means the product takes any purpose. A purpose the product does not accept is refused with 422. |
property_types | array of string enum | The property types this product may be ordered for. An empty list means the product takes any type. A type the product does not accept is refused with 422. |
OrderTypeList
| Field | Type | Description |
|---|---|---|
datarequired | array of OrderType | |
pagerequired | integer | |
per_pagerequired | integer | |
totalrequired | integer | How many items match in total. |
total_pagesrequired | integer |
BorrowerFields
| Field | Type | Description |
|---|---|---|
first_namerequired | string | |
last_namerequired | string | |
address | one of | The borrower's own address, when it is not the property address. |
receives_report | boolean | True to send the delivered report to this borrower. |
receives_status_updates | boolean | True to send status updates to this borrower. |
Borrower
| Field | Type | Description |
|---|---|---|
first_namerequired | string | |
last_namerequired | string | |
address | one of | The borrower's own address, when it is not the property address. |
receives_report | boolean | True to send the delivered report to this borrower. |
receives_status_updates | boolean | True to send status updates to this borrower. |
rolerequired | string | |
contactsrequired | array of Contact | Phone numbers and email addresses for the borrower. At least one is required. Either a phone number or an email address satisfies it; send a phone number where you have one, because that is how an appraiser arranges access. |
CoBorrower
| Field | Type | Description |
|---|---|---|
first_namerequired | string | |
last_namerequired | string | |
address | one of | The borrower's own address, when it is not the property address. |
receives_report | boolean | True to send the delivered report to this borrower. |
receives_status_updates | boolean | True to send status updates to this borrower. |
rolerequired | string | |
contacts | array of Contact | Phone numbers and email addresses for the co-borrower. Optional: the array may be empty or left out. |
BorrowerOrCoBorrower
role says which of the two this is, and which
rules apply: contacts are required on the borrower and optional on the
co-borrower. An order carries one borrower and at most one co-borrower.RealEstateAgent
| Field | Type | Description |
|---|---|---|
first_name | string or null | |
last_name | string or null | |
company | string or null | |
contacts | array of Contact |
AdditionalContact
report receives the delivered report; status
receives status updates.| Field | Type | Description |
|---|---|---|
purposerequired | string enum | One of: report, status |
name | string or null | |
emailrequired | string (email) |
Parties
| Field | Type | Description |
|---|---|---|
real_estate_agent | one of | |
additional_contacts | array of AdditionalContact |
Note
order notes are general instructions; appointment
notes are about arranging access. An order carries one note of each type.
Notes have no ids and cannot be edited or removed through this interface.| Field | Type | Description |
|---|---|---|
typerequired | string enum | One of: order, appointment |
textrequired | string |
OrderFlags
| Field | Type | Description |
|---|---|---|
rush | boolean | The lender is asking for a faster turn time. The appraisal management company decides whether a rush fee applies. |
complex | boolean | |
rural | boolean | |
priority | boolean | |
certified_appraiser_required | boolean | True when only a certified appraiser may take the assignment. |
LoanCreate
| Field | Type | Description |
|---|---|---|
purposerequired | string enum | Why the loan is being made. Send other with loan.purpose_other when nothing else fits.One of: construction_only, construction_to_permanent, mortgage_modification, other, purchase, refinance |
purpose_other | string or null | Required when purpose is other. |
number | string or null | The lender's loan number. |
client | string or null | The client the lender is acting for, when it is not the lender itself. |
investor | string or null | |
agency_case_number | string or null | |
fha_case_number | string or null | The case number for the loan. Required when the product's
appraiser_certification is fha_required or usda, accepted and
not required when it is fha_optional, and not used when it is
none. |
purchase_price | string or null | A decimal string with two places. Required when purpose is purchase. |
currency | string or null | The three letter currency code for the amounts on this order. Defaults to USD. |
Loan
| Field | Type | Description |
|---|---|---|
purposerequired | string enum | Why the loan is being made. Send other with loan.purpose_other when nothing else fits.One of: construction_only, construction_to_permanent, mortgage_modification, other, purchase, refinance |
purpose_other | string or null | Required when purpose is other. |
number | string or null | The lender's loan number. |
client | string or null | The client the lender is acting for, when it is not the lender itself. |
investor | string or null | |
agency_case_number | string or null | |
fha_case_number | string or null | The case number for the loan. Required when the product's
appraiser_certification is fha_required or usda, accepted and
not required when it is fha_optional, and not used when it is
none. |
purchase_price | string or null | A decimal string with two places. Required when purpose is purchase. |
currency | string or null | The three letter currency code for the amounts on this order. Defaults to USD. |
loan_type | one of | The loan type tier the order was placed on, for a product on the current report standard. |
add_ons | array of CatalogItem | The add-ons attached to the order. |
PropertyCreate
| Field | Type | Description |
|---|---|---|
addressrequired | Address | A United States street address. Properties and territories of the United
States only.
postal_code is required. city, state and county are filled in from
it when you leave them out, and the filled in values are returned on the
order. Where a postal code covers more than one place name we store the
postal service's preferred name. A postal code we cannot resolve is
refused with 422. |
typerequired | string enum | What kind of property is being appraised.One of: church, commercial_non_residential, condominium, condominium_over_four_stories, cooperative, farm, home_and_business_combined, manufactured_mobile_home, mixed_use_residential, multifamily_more_than_four_units, other, single_family, townhouse, two_to_four_unit_property, vacant_land |
occupancyrequired | string enum | How the property is occupied.One of: investment_property, primary_residence, second_home, vacant |
has_adu | boolean | True when the property has an accessory dwelling unit. Some add-ons on the current report standard apply only when this is true. |
Property
| Field | Type | Description |
|---|---|---|
addressrequired | Address | A United States street address. Properties and territories of the United
States only.
postal_code is required. city, state and county are filled in from
it when you leave them out, and the filled in values are returned on the
order. Where a postal code covers more than one place name we store the
postal service's preferred name. A postal code we cannot resolve is
refused with 422. |
typerequired | string enum | What kind of property is being appraised.One of: church, commercial_non_residential, condominium, condominium_over_four_stories, cooperative, farm, home_and_business_combined, manufactured_mobile_home, mixed_use_residential, multifamily_more_than_four_units, other, single_family, townhouse, two_to_four_unit_property, vacant_land |
occupancyrequired | string enum | How the property is occupied.One of: investment_property, primary_residence, second_home, vacant |
has_adu | boolean | True when the property has an accessory dwelling unit. |
OrderCreate
GET /order-types first: it gives you the
order_type_code to send and, for a product on the current report
standard, the loan_type_code and add_on_codes values that product
accepts.| Field | Type | Description |
|---|---|---|
order_type_coderequired | string | The product to order, from GET /order-types. |
loan_type_code | string or null | The loan type tier, from the product's loan_types. Required when the
product lists loan types. An unknown or inapplicable code is refused
with 422 rather than being guessed at. |
add_on_codes | array of string | Add-ons to attach, from the product's add_ons. |
due_daterequired | string (date) | The date the lender needs the report by. The appraisal management company confirms or adjusts it. |
lender_reference | string or null | Your own reference for this order. We store it and return it, and you can search on it. |
rush | boolean | |
complex | boolean | |
rural | boolean | |
priority | boolean | |
certified_appraiser_required | boolean | |
appraiser_instructions | string or null | Access instructions and anything else the appraiser needs to know. |
loanrequired | LoanCreate | The loan the appraisal supports. |
propertyrequired | PropertyCreate | The property to be appraised. |
borrowersrequired | array of BorrowerOrCoBorrower | The borrower, and a co-borrower when there is one. |
parties | Parties | Other people involved in the order. |
notes | array of Note | |
documents | array of InlineDocument | Supporting documents to attach at create, base64 encoded. Prefer
POST /orders/{order_id}/documents for anything over a megabyte or
two. |
InlineDocument
| Field | Type | Description |
|---|---|---|
kind | string | |
purpose | string enum | What a document you upload is for. Optional; other is assumed when you
leave it out.One of: engagement_letter, sales_contract, prior_report, other |
filenamerequired | string | |
content_typerequired | string | |
description | string or null | |
datarequired | string | The file's bytes, base64 encoded. The decoded size counts against the 25 MB limit. |
OrderPatch
| Field | Type | Description |
|---|---|---|
lender_reference | string or null | |
due_date | string (date) | A REQUEST to move the due date. The date changes only when the appraisal management company accepts it. |
appraiser_instructions | string or null | |
loan | object | Only the loan number, the client and the investor may be changed. |
borrower_contacts | array of Contact | Replaces the borrower's contact list. Names and the property cannot be changed. |
parties | Parties | Other people involved in the order. |
notes | array of Note | Notes to add to the order. An order carries one note of each type, and what you send is added to the note of that type rather than replacing it. Nothing already on the order is removed. |
Fees
| Field | Type | Description |
|---|---|---|
appraisal_feerequired | string or null | The fee the lender is charged, as a decimal string with two places. It
is normally set when the order is created. It is null when the product
or an add-on has to be quoted by the appraisal management company, and
it can change later. Either way order.fee_changed tells you. |
currencyrequired | string |
OrderDates
| Field | Type | Description |
|---|---|---|
created_atrequired | string (date-time) | |
updated_atrequired | string (date-time) | When anything you can see on the order last changed: its status, its
dates, its fee, its documents, its messages or its own fields. This is
the field updated_since filters on. |
due_daterequired | string (date) | |
appointment_at | string or null (date-time) | The inspection appointment, when one has been scheduled. |
completed_at | string or null (date-time) | When the report was delivered. |
AppraiserRef
appraiser is null.| Field | Type | Description |
|---|---|---|
namerequired | string |
Order
| Field | Type | Description |
|---|---|---|
idrequired | string | Our id for the order. Always starts with ord_. |
order_numberrequired | string | The order number the appraisal management company uses, the one a person will quote on the phone. |
lender_reference | string or null | |
statusrequired | OrderStatus | A status, as a stable code with display text. |
order_typerequired | OrderTypeRef | The product an order was placed against. |
loanrequired | Loan | |
propertyrequired | Property | The property on an order, as it is read back. |
borrowers | array of BorrowerOrCoBorrower | |
parties | Parties | Other people involved in the order. |
notes | array of Note | |
flags | OrderFlags | The handling flags on the order. |
appraiser_instructions | string or null | |
appraiser | one of | |
datesrequired | OrderDates | The dates on the order. |
feesrequired | Fees | The fee the lender is charged. Read only through this API. |
documents | array of DocumentSummary | The documents on the order, without download links. |
OrderSummary
| Field | Type | Description |
|---|---|---|
idrequired | string | |
order_numberrequired | string | |
lender_reference | string or null | |
statusrequired | OrderStatus | A status, as a stable code with display text. |
order_typerequired | OrderTypeRef | The product an order was placed against. |
property_address_summary | string | The property address on one line, for display. |
datesrequired | OrderDates | The dates on the order. |
OrderList
| Field | Type | Description |
|---|---|---|
datarequired | array of OrderSummary | |
pagerequired | integer | |
per_pagerequired | integer | |
totalrequired | integer | How many items match in total. |
total_pagesrequired | integer |
ActionRequest
| Field | Type | Description |
|---|---|---|
reason | string |
OrderActionResult
| Field | Type | Description |
|---|---|---|
idrequired | string | |
order_numberrequired | string | |
statusrequired | OrderStatus | A status, as a stable code with display text. |
previous_status | OrderStatusRef | A status without a timestamp, used for a previous status. |
RevisionKind
correction asks the appraiser to fix or clarify the report.
reconsideration_of_value asks the appraiser to reconsider the opinion of
value and requires at least one acknowledgement.One of: correction, reconsideration_of_value
RevisionAcknowledgements
| Field | Type | Description |
|---|---|---|
prior_appraisal_provided | boolean | |
comparable_sales_provided | boolean |
RevisionRequestCreate
| Field | Type | Description |
|---|---|---|
kindrequired | string enum | correction asks the appraiser to fix or clarify the report.
reconsideration_of_value asks the appraiser to reconsider the opinion of
value and requires at least one acknowledgement.One of: correction, reconsideration_of_value |
reasonrequired | string | What needs to change, and why. |
acknowledgements | RevisionAcknowledgements | Required on a reconsideration of value. At least one must be true, or the request is refused with 422. |
document_ids | array of string | Documents already uploaded to this order that support the request. |
documents | array of InlineDocument | Documents to attach inline instead of uploading first. |
RevisionResponse
| Field | Type | Description |
|---|---|---|
idrequired | string | |
created_atrequired | string (date-time) | |
authorrequired | Author | Who wrote a message. People are identified by display name only. |
messagerequired | string | |
documents | array of DocumentSummary |
RevisionRequest
| Field | Type | Description |
|---|---|---|
idrequired | string | Always starts with rr_. |
order_idrequired | string | |
kindrequired | string enum | correction asks the appraiser to fix or clarify the report.
reconsideration_of_value asks the appraiser to reconsider the opinion of
value and requires at least one acknowledgement.One of: correction, reconsideration_of_value |
statusrequired | string enum | submitted while the appraisal management company reviews it,
accepted once it is with the appraiser, declined when the company
does not take it forward, and
completed once a revised report has been delivered against it.One of: submitted, accepted, declined, completed |
reasonrequired | string | |
acknowledgements | RevisionAcknowledgements | Required on a reconsideration of value. At least one must be true, or the request is refused with 422. |
documents | array of DocumentSummary | |
responses | array of RevisionResponse | |
created_atrequired | string (date-time) | |
updated_atrequired | string (date-time) |
RevisionRequestList
| Field | Type | Description |
|---|---|---|
datarequired | array of RevisionRequest | |
pagerequired | integer | |
per_pagerequired | integer | |
totalrequired | integer | How many items match in total. |
total_pagesrequired | integer |
Author
| Field | Type | Description |
|---|---|---|
typerequired | string enum | One of: lender, manager, appraiser, system |
namerequired | string |
MessageCreate
| Field | Type | Description |
|---|---|---|
recipientrequired | string enum | Who the message is for. A company that keeps appraiser contact in its
own hands refuses appraiser with 422 and code
recipient_not_allowed.One of: manager, appraiser |
subject | string or null | |
bodyrequired | string | |
document_ids | array of string | Documents already uploaded to this order to attach. |
Message
| Field | Type | Description |
|---|---|---|
idrequired | string | Always starts with msg_. |
order_idrequired | string | |
recipientrequired | string enum | Who the message was addressed to.One of: manager, appraiser, lender |
subject | string or null | |
bodyrequired | string | |
authorrequired | Author | Who wrote a message. People are identified by display name only. |
attachments | array of DocumentSummary | |
created_atrequired | string (date-time) |
MessageList
| Field | Type | Description |
|---|---|---|
datarequired | array of Message | |
pagerequired | integer | |
per_pagerequired | integer | |
totalrequired | integer | How many items match in total. |
total_pagesrequired | integer |
DocumentKind
report_pdf: the appraisal report as a PDF.report_data: the report data. Onuad_2_6it is the MISMO 2.6 GSE appraisal XML, with the report PDF embedded as that standard defines. Onuad_3_6it is the UAD 3.6 delivery package, a ZIP produced by the appraiser's forms software to the GSE UAD 3.6 specification, whose members are defined by that specification. The package is delivered exactly as the forms software produced it, so whether a copy of the report PDF sits inside it is that software's doing. Either wayreport_pdfis always delivered as its own file as well, and that is the copy to read.invoice: the invoice for the order. Always a separate file, and never inside the package.compliance_certificate: the compliance certificate.borrower_certificate: the borrower delivery certificate.ssr: a submission summary report from the collateral delivery portal.review_report: a quality review report produced by the appraisal management company's own review process, when the company provides it to lenders. It is not something a lender orders through this API.supporting: anything supplied to support the order, by either side.
One of: report_pdf, report_data, invoice, compliance_certificate, borrower_certificate, ssr, review_report, supporting
DocumentSummary
| Field | Type | Description |
|---|---|---|
idrequired | string | Always starts with doc_. |
kindrequired | string enum | What a document is.
report_pdf, report_data, invoice, compliance_certificate, borrower_certificate, ssr, review_report, supporting |
filenamerequired | string | |
content_typerequired | string | |
size_bytes | integer or null | |
description | string or null | |
created_atrequired | string (date-time) |
Download
| Field | Type | Description |
|---|---|---|
urlrequired | string (uri) | Follow it with a plain GET and no Authorization header: the signature
in the link is the authorization. Its expires value is expires_at
in Unix seconds. |
expires_atrequired | string (date-time) | When the link stops working. Ask for another one after that. |
Document
| Field | Type | Description |
|---|---|---|
idrequired | string | Always starts with doc_. |
kindrequired | string enum | What a document is.
report_pdf, report_data, invoice, compliance_certificate, borrower_certificate, ssr, review_report, supporting |
filenamerequired | string | |
content_typerequired | string | |
size_bytes | integer or null | |
description | string or null | |
created_atrequired | string (date-time) | |
order_idrequired | string | |
downloadrequired | Download | A signed link to the file. It is valid for five minutes and may be used more than once inside that window. Fetch a fresh link rather than storing one. |
DocumentList
| Field | Type | Description |
|---|---|---|
datarequired | array of DocumentSummary | |
pagerequired | integer | |
per_pagerequired | integer | |
totalrequired | integer | How many items match in total. |
total_pagesrequired | integer |
DocumentPurpose
other is assumed when you
leave it out.One of: engagement_letter, sales_contract, prior_report, other
DocumentUpload
| Field | Type | Description |
|---|---|---|
filerequired | string (binary) | The file. Up to 25 MB. |
kindrequired | string | Only supporting may be uploaded by a lender. |
purpose | string enum | What a document you upload is for. Optional; other is assumed when you
leave it out.One of: engagement_letter, sales_contract, prior_report, other |
description | string | What the file is, for the appraiser. |
DeliveryStatus
pending: not yet attempted, or waiting for its next attempt.delivered: your endpoint returned a 2xx.failed: at least one attempt failed and another is scheduled.dead_lettered: every attempt failed. We will not try again, and the event stays readable here.not_subscribed: raised but not delivered, because your subscription does not include this type.
One of: pending, delivered, failed, dead_lettered, not_subscribed
EventDelivery
| Field | Type | Description |
|---|---|---|
statusrequired | string enum | How delivery of an event to your endpoint is going.
pending, delivered, failed, dead_lettered, not_subscribed |
attemptsrequired | integer | |
last_attempt_at | string or null (date-time) | |
next_attempt_at | string or null (date-time) | |
last_response_status | integer or null | The HTTP status your endpoint returned on the last attempt. |
EventType
One of: order.created, order.status_changed, order.assigned, order.on_hold, order.resumed, order.cancelled, order.completed, order.document_added, order.message_posted, order.revision_requested, order.revision_responded, order.due_date_changed, order.fee_changed
Event
| Field | Type | Description |
|---|---|---|
idrequired | string | Always starts with evt_. Ids are lexicographically sortable and come
out in the order the events were raised. Compare them as strings; do
not decode one. |
typerequired | string enum | The event catalog.One of: order.created, order.status_changed, order.assigned, order.on_hold, order.resumed, order.cancelled, order.completed, order.document_added, order.message_posted, order.revision_requested, order.revision_responded, order.due_date_changed, order.fee_changed |
created_atrequired | string (date-time) | |
order_idrequired | string | Every event type in version 1 is an order event, so this is always set. |
datarequired | object | The same payload we deliver to your endpoint for this event, without
the envelope fields. Its schema is the one published under webhooks
for this type. |
deliveryrequired | EventDelivery | The delivery state of one event. |
EventList
next_cursor back as
after until it comes back null.| Field | Type | Description |
|---|---|---|
datarequired | array of Event | |
next_cursorrequired | string or null | Pass this as after to read the next page. Null when you have reached the end. |
WebhookConfig
| Field | Type | Description |
|---|---|---|
urlrequired | string (uri) | |
enabledrequired | boolean | |
eventsrequired | array of string | The event types you are subscribed to, or ["*"] for all of them. |
secret_setrequired | boolean | True when a signing secret is set. The secret itself is never returned. |
secret_rotated_at | string or null (date-time) | |
updated_at | string or null (date-time) |
WebhookConfigUpdate
events keeps your subscription, and omitting
secret keeps your secret. url is always required.| Field | Type | Description |
|---|---|---|
urlrequired | string (uri) | An HTTPS URL that answers a POST with a 2xx within 10 seconds. |
enabled | boolean | Send false to stop delivery without losing your configuration. |
events | array of string | Event types to subscribe to, or ["*"] for all of them. Leave it out
to keep your current subscription. |
secret | string | Set or rotate the signing secret. At least 32 characters of random text. Never returned, and never cleared by this call: leave it out to keep the secret you have. |
WebhookEnvelope
type, and use id to
make your handler idempotent: a redelivery carries the same id.| Field | Type | Description |
|---|---|---|
idrequired | string | The event id, the same value as X-AH-Event-Id. |
typerequired | string enum | The event catalog.One of: order.created, order.status_changed, order.assigned, order.on_hold, order.resumed, order.cancelled, order.completed, order.document_added, order.message_posted, order.revision_requested, order.revision_responded, order.due_date_changed, order.fee_changed |
created_atrequired | string (date-time) | When we raised the event, not when we delivered it. |
api_versionrequired | string | The version of this contract the payload was built to. |
test | boolean | True only on a specimen event sent by POST /webhook/test. Never true
on a real event, and a test event is not written to your feed. A
specimen carries a synthetic data.order_id, always prefixed
ord_test_, which no real order in any environment ever carries, so
it can never match one of your orders. When test is true, verify
the signature, answer 2xx, and stop: do not store the event and do
not look the order up. This holds in production as well as in the
sandbox. |
datarequired | object |
EventOrderRef
| Field | Type | Description |
|---|---|---|
order_idrequired | string | |
order_numberrequired | string |
EventOrderCreated
| Field | Type | Description |
|---|---|---|
idrequired | string | The event id, the same value as X-AH-Event-Id. |
typerequired | string enum | The event catalog.One of: order.created, order.status_changed, order.assigned, order.on_hold, order.resumed, order.cancelled, order.completed, order.document_added, order.message_posted, order.revision_requested, order.revision_responded, order.due_date_changed, order.fee_changed |
created_atrequired | string (date-time) | When we raised the event, not when we delivered it. |
api_versionrequired | string | The version of this contract the payload was built to. |
test | boolean | True only on a specimen event sent by POST /webhook/test. Never true
on a real event, and a test event is not written to your feed. A
specimen carries a synthetic data.order_id, always prefixed
ord_test_, which no real order in any environment ever carries, so
it can never match one of your orders. When test is true, verify
the signature, answer 2xx, and stop: do not store the event and do
not look the order up. This holds in production as well as in the
sandbox. |
datarequired | object |
EventOrderStatusChanged
| Field | Type | Description |
|---|---|---|
idrequired | string | The event id, the same value as X-AH-Event-Id. |
typerequired | string enum | The event catalog.One of: order.created, order.status_changed, order.assigned, order.on_hold, order.resumed, order.cancelled, order.completed, order.document_added, order.message_posted, order.revision_requested, order.revision_responded, order.due_date_changed, order.fee_changed |
created_atrequired | string (date-time) | When we raised the event, not when we delivered it. |
api_versionrequired | string | The version of this contract the payload was built to. |
test | boolean | True only on a specimen event sent by POST /webhook/test. Never true
on a real event, and a test event is not written to your feed. A
specimen carries a synthetic data.order_id, always prefixed
ord_test_, which no real order in any environment ever carries, so
it can never match one of your orders. When test is true, verify
the signature, answer 2xx, and stop: do not store the event and do
not look the order up. This holds in production as well as in the
sandbox. |
datarequired | object |
EventOrderAssigned
| Field | Type | Description |
|---|---|---|
idrequired | string | The event id, the same value as X-AH-Event-Id. |
typerequired | string enum | The event catalog.One of: order.created, order.status_changed, order.assigned, order.on_hold, order.resumed, order.cancelled, order.completed, order.document_added, order.message_posted, order.revision_requested, order.revision_responded, order.due_date_changed, order.fee_changed |
created_atrequired | string (date-time) | When we raised the event, not when we delivered it. |
api_versionrequired | string | The version of this contract the payload was built to. |
test | boolean | True only on a specimen event sent by POST /webhook/test. Never true
on a real event, and a test event is not written to your feed. A
specimen carries a synthetic data.order_id, always prefixed
ord_test_, which no real order in any environment ever carries, so
it can never match one of your orders. When test is true, verify
the signature, answer 2xx, and stop: do not store the event and do
not look the order up. This holds in production as well as in the
sandbox. |
datarequired | object |
EventOrderOnHold
| Field | Type | Description |
|---|---|---|
idrequired | string | The event id, the same value as X-AH-Event-Id. |
typerequired | string enum | The event catalog.One of: order.created, order.status_changed, order.assigned, order.on_hold, order.resumed, order.cancelled, order.completed, order.document_added, order.message_posted, order.revision_requested, order.revision_responded, order.due_date_changed, order.fee_changed |
created_atrequired | string (date-time) | When we raised the event, not when we delivered it. |
api_versionrequired | string | The version of this contract the payload was built to. |
test | boolean | True only on a specimen event sent by POST /webhook/test. Never true
on a real event, and a test event is not written to your feed. A
specimen carries a synthetic data.order_id, always prefixed
ord_test_, which no real order in any environment ever carries, so
it can never match one of your orders. When test is true, verify
the signature, answer 2xx, and stop: do not store the event and do
not look the order up. This holds in production as well as in the
sandbox. |
datarequired | object |
EventOrderResumed
| Field | Type | Description |
|---|---|---|
idrequired | string | The event id, the same value as X-AH-Event-Id. |
typerequired | string enum | The event catalog.One of: order.created, order.status_changed, order.assigned, order.on_hold, order.resumed, order.cancelled, order.completed, order.document_added, order.message_posted, order.revision_requested, order.revision_responded, order.due_date_changed, order.fee_changed |
created_atrequired | string (date-time) | When we raised the event, not when we delivered it. |
api_versionrequired | string | The version of this contract the payload was built to. |
test | boolean | True only on a specimen event sent by POST /webhook/test. Never true
on a real event, and a test event is not written to your feed. A
specimen carries a synthetic data.order_id, always prefixed
ord_test_, which no real order in any environment ever carries, so
it can never match one of your orders. When test is true, verify
the signature, answer 2xx, and stop: do not store the event and do
not look the order up. This holds in production as well as in the
sandbox. |
datarequired | object |
EventOrderCancelled
| Field | Type | Description |
|---|---|---|
idrequired | string | The event id, the same value as X-AH-Event-Id. |
typerequired | string enum | The event catalog.One of: order.created, order.status_changed, order.assigned, order.on_hold, order.resumed, order.cancelled, order.completed, order.document_added, order.message_posted, order.revision_requested, order.revision_responded, order.due_date_changed, order.fee_changed |
created_atrequired | string (date-time) | When we raised the event, not when we delivered it. |
api_versionrequired | string | The version of this contract the payload was built to. |
test | boolean | True only on a specimen event sent by POST /webhook/test. Never true
on a real event, and a test event is not written to your feed. A
specimen carries a synthetic data.order_id, always prefixed
ord_test_, which no real order in any environment ever carries, so
it can never match one of your orders. When test is true, verify
the signature, answer 2xx, and stop: do not store the event and do
not look the order up. This holds in production as well as in the
sandbox. |
datarequired | object |
EventOrderCompleted
| Field | Type | Description |
|---|---|---|
idrequired | string | The event id, the same value as X-AH-Event-Id. |
typerequired | string enum | The event catalog.One of: order.created, order.status_changed, order.assigned, order.on_hold, order.resumed, order.cancelled, order.completed, order.document_added, order.message_posted, order.revision_requested, order.revision_responded, order.due_date_changed, order.fee_changed |
created_atrequired | string (date-time) | When we raised the event, not when we delivered it. |
api_versionrequired | string | The version of this contract the payload was built to. |
test | boolean | True only on a specimen event sent by POST /webhook/test. Never true
on a real event, and a test event is not written to your feed. A
specimen carries a synthetic data.order_id, always prefixed
ord_test_, which no real order in any environment ever carries, so
it can never match one of your orders. When test is true, verify
the signature, answer 2xx, and stop: do not store the event and do
not look the order up. This holds in production as well as in the
sandbox. |
datarequired | object |
EventOrderDocumentAdded
| Field | Type | Description |
|---|---|---|
idrequired | string | The event id, the same value as X-AH-Event-Id. |
typerequired | string enum | The event catalog.One of: order.created, order.status_changed, order.assigned, order.on_hold, order.resumed, order.cancelled, order.completed, order.document_added, order.message_posted, order.revision_requested, order.revision_responded, order.due_date_changed, order.fee_changed |
created_atrequired | string (date-time) | When we raised the event, not when we delivered it. |
api_versionrequired | string | The version of this contract the payload was built to. |
test | boolean | True only on a specimen event sent by POST /webhook/test. Never true
on a real event, and a test event is not written to your feed. A
specimen carries a synthetic data.order_id, always prefixed
ord_test_, which no real order in any environment ever carries, so
it can never match one of your orders. When test is true, verify
the signature, answer 2xx, and stop: do not store the event and do
not look the order up. This holds in production as well as in the
sandbox. |
datarequired | object |
EventOrderMessagePosted
| Field | Type | Description |
|---|---|---|
idrequired | string | The event id, the same value as X-AH-Event-Id. |
typerequired | string enum | The event catalog.One of: order.created, order.status_changed, order.assigned, order.on_hold, order.resumed, order.cancelled, order.completed, order.document_added, order.message_posted, order.revision_requested, order.revision_responded, order.due_date_changed, order.fee_changed |
created_atrequired | string (date-time) | When we raised the event, not when we delivered it. |
api_versionrequired | string | The version of this contract the payload was built to. |
test | boolean | True only on a specimen event sent by POST /webhook/test. Never true
on a real event, and a test event is not written to your feed. A
specimen carries a synthetic data.order_id, always prefixed
ord_test_, which no real order in any environment ever carries, so
it can never match one of your orders. When test is true, verify
the signature, answer 2xx, and stop: do not store the event and do
not look the order up. This holds in production as well as in the
sandbox. |
datarequired | object |
EventOrderRevisionRequested
| Field | Type | Description |
|---|---|---|
idrequired | string | The event id, the same value as X-AH-Event-Id. |
typerequired | string enum | The event catalog.One of: order.created, order.status_changed, order.assigned, order.on_hold, order.resumed, order.cancelled, order.completed, order.document_added, order.message_posted, order.revision_requested, order.revision_responded, order.due_date_changed, order.fee_changed |
created_atrequired | string (date-time) | When we raised the event, not when we delivered it. |
api_versionrequired | string | The version of this contract the payload was built to. |
test | boolean | True only on a specimen event sent by POST /webhook/test. Never true
on a real event, and a test event is not written to your feed. A
specimen carries a synthetic data.order_id, always prefixed
ord_test_, which no real order in any environment ever carries, so
it can never match one of your orders. When test is true, verify
the signature, answer 2xx, and stop: do not store the event and do
not look the order up. This holds in production as well as in the
sandbox. |
datarequired | object |
EventOrderRevisionResponded
| Field | Type | Description |
|---|---|---|
idrequired | string | The event id, the same value as X-AH-Event-Id. |
typerequired | string enum | The event catalog.One of: order.created, order.status_changed, order.assigned, order.on_hold, order.resumed, order.cancelled, order.completed, order.document_added, order.message_posted, order.revision_requested, order.revision_responded, order.due_date_changed, order.fee_changed |
created_atrequired | string (date-time) | When we raised the event, not when we delivered it. |
api_versionrequired | string | The version of this contract the payload was built to. |
test | boolean | True only on a specimen event sent by POST /webhook/test. Never true
on a real event, and a test event is not written to your feed. A
specimen carries a synthetic data.order_id, always prefixed
ord_test_, which no real order in any environment ever carries, so
it can never match one of your orders. When test is true, verify
the signature, answer 2xx, and stop: do not store the event and do
not look the order up. This holds in production as well as in the
sandbox. |
datarequired | object |
EventOrderDueDateChanged
| Field | Type | Description |
|---|---|---|
idrequired | string | The event id, the same value as X-AH-Event-Id. |
typerequired | string enum | The event catalog.One of: order.created, order.status_changed, order.assigned, order.on_hold, order.resumed, order.cancelled, order.completed, order.document_added, order.message_posted, order.revision_requested, order.revision_responded, order.due_date_changed, order.fee_changed |
created_atrequired | string (date-time) | When we raised the event, not when we delivered it. |
api_versionrequired | string | The version of this contract the payload was built to. |
test | boolean | True only on a specimen event sent by POST /webhook/test. Never true
on a real event, and a test event is not written to your feed. A
specimen carries a synthetic data.order_id, always prefixed
ord_test_, which no real order in any environment ever carries, so
it can never match one of your orders. When test is true, verify
the signature, answer 2xx, and stop: do not store the event and do
not look the order up. This holds in production as well as in the
sandbox. |
datarequired | object |
EventOrderFeeChanged
| Field | Type | Description |
|---|---|---|
idrequired | string | The event id, the same value as X-AH-Event-Id. |
typerequired | string enum | The event catalog.One of: order.created, order.status_changed, order.assigned, order.on_hold, order.resumed, order.cancelled, order.completed, order.document_added, order.message_posted, order.revision_requested, order.revision_responded, order.due_date_changed, order.fee_changed |
created_atrequired | string (date-time) | When we raised the event, not when we delivered it. |
api_versionrequired | string | The version of this contract the payload was built to. |
test | boolean | True only on a specimen event sent by POST /webhook/test. Never true
on a real event, and a test event is not written to your feed. A
specimen carries a synthetic data.order_id, always prefixed
ord_test_, which no real order in any environment ever carries, so
it can never match one of your orders. When test is true, verify
the signature, answer 2xx, and stop: do not store the event and do
not look the order up. This holds in production as well as in the
sandbox. |
datarequired | object |