Appraisal Host - Appraisal Management Software for AMCs and Lenders

Developer documentation

OpenAPI 3.1 spec

Guide

Appraisal Host APIAuthenticationSandboxOrder lifecycleWebhooksReference notesChangelogSupport

API reference

Every endpoint

Order lifecycle

Everything from reading the product catalog to receiving the finished report package.

1. Read the product catalog first

GET /order-types returns the products the lender may order. Read it before you place an order, and read it again when you cache it: it tells you the report format the product is delivered in, which appraiser certification it requires, what it may be ordered for, and which loan types and add-ons may be attached.

curl -s https://api.appraisalhost.com/v1/order-types \
  -H 'Authorization: Bearer aht_at_7Qk2rX9wTm4ZbN1sV6yH0pL8'
{
  "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
}

Report format

report_formatWhat you sendWhat comes back
uad_2_6The prior report standard. No loan type tier. Add-ons may still apply.The report as a PDF, plus the report data as an XML file.
uad_3_6The current report standard. A loan_type_code is required when the product lists loan types, and add-ons may apply.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 replaces the report data file only. It never contains the invoice.

What report_data is

This is the file your system parses, so here is exactly what it is.

  • On uad_2_6, report_data is the MISMO 2.6 GSE appraisal XML, with the report PDF embedded as that standard defines. Media type application/xml. It is delivered alongside the separate report_pdf document.
  • On uad_3_6, report_data is 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, and their names, are defined by that specification. Media type application/zip. The package is delivered exactly as the appraiser's forms software produced it, so whether a copy of the report PDF sits inside it is that software's doing and not ours. report_pdf is always delivered as its own file as well, and that is the copy to read: take the PDF from the report_pdf document rather than from inside the package.

On both standards the invoice and the certificates are always separate documents with their own kind. Nothing is inside the package that the specification does not put there, and the invoice never is.

Sample files for both formats are available from our integrations team: ask at integrations@appraisalhost.com before you scope the parsing work.

Loan types and add-ons

A product may be scoped on a loan type tier, and may carry add-ons. Both come from the product, so read them from GET /order-types rather than writing codes into your source:

  • loan_type_code is required only on a product whose loan_types list is not empty, which today means products on the current report standard. Send the code, not the name.
  • add_on_codes are optional and must come from that product's own add_ons. Add-ons are not particular to one report standard: a rent schedule, an operating income statement and others apply on products of either standard, so always read the product's own list rather than assuming.
  • loan_purposes and property_types on the product say what it may be ordered for. An empty list means no restriction; a value the product does not accept is refused with 422.
  • 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 you learn the price from order.fee_changed.
  • Some add-ons apply only when the property has an accessory dwelling unit. GET /order-types lists the add-ons that apply to a property without one by default. Pass has_adu=true to get that list plus the add-ons that need an accessory dwelling unit, and send property.has_adu on the order itself.
  • Codes are stable for a company. Names are display text and may be reworded.
  • A product appears here only when the appraisal management company has enabled it for API ordering and given it a code. Codes are the company's own: treat them as opaque strings, because some companies use numbers.
  • An unknown or inapplicable code is refused with 422 and code semantic_validation_failed rather than being guessed at, so that an order is never quietly priced on a tier you did not ask for.

active is false for a product the company has withdrawn; it cannot be ordered. A product this lender is not entitled to order does not appear in the list at all. The list is ordered by code, ascending.

2. Place an order

POST /orders. Always send an Idempotency-Key.

Required: order_type_code, due_date, loan.purpose, the property address with a postal code, the property type and occupancy, and one borrower with at least one entry in contacts.

  • Borrowers. Send one borrower, and a co-borrower when there is one: the array holds at most two people. On the borrower, role, first_name, last_name and at least one contacts entry are required. On a co-borrower, role, first_name and last_name are required and contacts are optional, and the contract says the same: the borrower and the co-borrower are separate schemas in it, so a generated client serialises a co-borrower with no contacts and refuses a borrower with none. A borrower with no contacts is refused with 422, and details[].field is borrowers.0.contacts. 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.
  • The property address. United States properties and territories only. property.postal_code is required. City, state and county are filled in from it when you leave them out, and the filled in values come back on the order. Where a postal code covers more than one place name we store the postal service's preferred name for it. A postal code we cannot resolve is refused with 422.

Conditional requirements

The fields that are required only sometimes, in one place:

FieldRequired whenRefused with
loan_type_codeThe product's loan_types list is not empty.422, semantic_validation_failed
loan.purpose_otherloan.purpose is other.422, semantic_validation_failed
loan.fha_case_numberThe product's appraiser_certification is fha_required or usda.422, semantic_validation_failed
loan.purchase_priceloan.purpose is purchase.422, semantic_validation_failed
borrowers[0].contactsAlways, on the borrower. A co-borrower's contacts are optional.422, validation_failed
property.has_aduYou are attaching an add-on that applies only to a property with an accessory dwelling unit.422, semantic_validation_failed

An order type may not accept every property type or every loan purpose. Read loan_purposes and property_types on the product and send values from them; a value the product does not accept is refused with 422.

A product on the current report standard

curl -s -X POST https://api.appraisalhost.com/v1/orders \
  -H 'Authorization: Bearer aht_at_7Qk2rX9wTm4ZbN1sV6yH0pL8' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: los-88421-create-1' \
  -d '{
    "order_type_code": "SFR-1004-36",
    "loan_type_code": "conventional",
    "add_on_codes": ["rent_schedule"],
    "due_date": "2026-10-02",
    "lender_reference": "LN-2026-88421",
    "rush": false,
    "certified_appraiser_required": true,
    "appraiser_instructions": "Gate code 4417. Call the listing agent for access.",
    "loan": {
      "purpose": "purchase",
      "number": "88421",
      "client": "Example Mortgage Group",
      "purchase_price": "415000.00",
      "currency": "USD"
    },
    "property": {
      "address": {
        "street": "100 Example Avenue",
        "unit": "Unit 2",
        "city": "Springfield",
        "state": "IL",
        "postal_code": "62701"
      },
      "type": "single_family",
      "occupancy": "primary_residence",
      "has_adu": true
    },
    "borrowers": [
      {
        "role": "borrower",
        "first_name": "Sample",
        "last_name": "Borrower",
        "receives_status_updates": true,
        "contacts": [
          { "type": "email", "role": "home", "value": "sample.borrower@example.com" },
          { "type": "phone", "role": "cell", "value": "+1-217-555-0142" }
        ]
      }
    ],
    "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" }
      ]
    },
    "notes": [
      { "type": "order", "text": "Borrower prefers a morning appointment." }
    ]
  }'
{
  "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",
    "number": "88421",
    "purchase_price": "415000.00",
    "currency": "USD",
    "loan_type": { "code": "conventional", "name": "Conventional" },
    "add_ons": [{ "code": "rent_schedule", "name": "Rent Schedule" }]
  },
  "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": []
}

Store id and order_number against your loan file. id is what you call us with. order_number is what a person will quote on the phone.

A product on the prior report standard

curl -s -X POST https://api.appraisalhost.com/v1/orders \
  -H 'Authorization: Bearer aht_at_7Qk2rX9wTm4ZbN1sV6yH0pL8' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: los-88422-create-1' \
  -d '{
    "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" }
        ]
      }
    ]
  }'

Appraiser certification, FHA and USDA

appraiser_certification on the product says which appraiser certification it requires, and it is what the case number rule follows:

appraiser_certificationWhat it meansloan.fha_case_number
noneNo special certification.Not used.
fha_requiredOnly an FHA approved appraiser may take it.Required. Omitting it is refused with 422.
fha_optionalAn FHA approved appraiser may take it.Accepted, not required.
usdaA USDA product.Required. Omitting it is refused with 422.

After the order is accepted

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, because of the product, the loan type or the property, is at pending_review and moves to new when the company places it. Both are normal, and you will see the order move with order.status_changed.

A request we can refuse on its own terms, 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.

3. Follow the order

The catalog below is the complete set of statuses this interface reports. An order is always reported with the status the lender sees, in the same words the lender sees in the portal. Not every step inside the appraisal management company produces a status change, so treat each status as a fact about now.

codelabelWhat it means
pending_reviewPending ReviewReceived, and with the appraisal management company for a review before it is worked. Nothing is wrong. You will receive order.status_changed when it moves.
newNew OrderReceived. Not yet assigned.
appraiser_assignedAppraiser AssignedAn appraiser has the assignment.
appraiser_acceptedAppraiser AcceptedThe appraiser has accepted it.
borrower_contactedBorrower ContactedThe appraiser has reached the contact.
left_message_for_borrowerLeft message for borrower / brokerThe appraiser has tried the contact and left a message.
appointment_scheduledAppointment ScheduledAn inspection appointment is set. dates.appointment_at carries it.
awaiting_reviewReport Submitted, Awaiting ReviewThe report has been submitted and is in review before delivery.
report_completeReport CompleteThe report has been delivered. The documents are on the order.
report_rejected_for_correctionReport Rejected for CorrectionThe report was sent back for correction before delivery.
revision_requestedCorrection Requested By the LenderA correction has been requested on a delivered report.
reconsideration_requestedRequest a reconsideration of valueA reconsideration of value has been requested.
revised_report_completeRevised Report CompletedA revised report has been delivered.
on_holdOn HoldWork is paused.
off_holdOff HoldWork has resumed after a hold.
cancelledOrder CancelledThe order was cancelled.
reactivatedOrder ReactivatedA cancelled order has been put back into production.

The labels above are one company's wording, shown as an example. Another company may word the same code differently, and a few labels are ours rather than the company's, because the status they stand for is internal to the company.

Not every status occurs at every company: a company may not use one at all. Treat the catalog as the full set of what you may receive, never as a sequence you must see.

Two rules for handling statuses:

  1. Branch on code, display label. An appraisal management company may reword its own labels. Codes do not change.
  2. Do not assume a fixed sequence. Orders skip statuses, repeat them, and go backwards. An order can be delivered, corrected and delivered again. Treat each status as a fact about now, not a step in a queue.

off_hold and reactivated are transitional: they say what just happened, not what the order is doing. An order at either moves on to its working status shortly afterwards, so read the order again when you see one rather than treating it as a resting state.

Webhooks are the primary way to learn about change. Poll only to reconcile:

curl -s 'https://api.appraisalhost.com/v1/orders?updated_since=2026-09-18T00:00:00Z&per_page=50' \
  -H 'Authorization: Bearer aht_at_7Qk2rX9wTm4ZbN1sV6yH0pL8'

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. updated_since is inclusive to the second, so overlap your windows by a second or two rather than trusting an exact boundary.

4. Hold, resume, cancel

These are the rules this interface enforces. The appraisal management company's own screens are slightly wider in places, so an order you cannot hold here may still be held by the company on request. When the order's current status does not allow an action, we answer 409 with code action_not_allowed_in_status and the order's current status in current_status.

ActionAllowed whenRefused with 409 when
holdThe order is open and not already on hold, and no report has been delivered.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.
resumeThe order is on hold.Any other status.
cancelThe order is open and no report has been delivered.The report has been delivered, a correction is open, or the order is already cancelled. A held order must be resumed first.
curl -s -X POST https://api.appraisalhost.com/v1/orders/ord_9TBK4C2QFA7M/hold \
  -H 'Authorization: Bearer aht_at_7Qk2rX9wTm4ZbN1sV6yH0pL8' \
  -H 'Content-Type: application/json' \
  -d '{ "reason": "Borrower is renegotiating the purchase price." }'
{
  "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" }
}

A refusal looks like this:

{
  "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"
}

Branch on current_status, the top level field. Every 409 that refuses an action because of where the order has got to carries it, so you never have to walk details, and never have to read message. details[].value carries the same machine readable value for anything else at fault. message is for a person and may be reworded at any time.

Send a reason. The appraisal management company and the appraiser both see it, and it saves a phone call. Note that a hold stands the appraiser down and remembers them, so a resume puts the order back where it was.

If the company cannot take an order on at all, it cancels it: you receive order.cancelled with a reason, and the order is at cancelled. You learn it within seconds rather than by noticing an order that never moved.

Some companies do not let a lender cancel 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.

5. Corrections and reconsiderations of value

A revision request is how a lender asks for something to change after a report has been delivered.

  • kind: "correction" asks the appraiser to fix or clarify the report.
  • kind: "reconsideration_of_value" asks the appraiser to reconsider the opinion of value. At least one acknowledgement is required: that a prior appraisal was provided, or that comparable sales were provided. Without one, the request is refused with 422.

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.

Attach your evidence. Upload it first and quote the document ids, or send it inline:

curl -s -X POST https://api.appraisalhost.com/v1/orders/ord_9TBK4C2QFA7M/revision-requests \
  -H 'Authorization: Bearer aht_at_7Qk2rX9wTm4ZbN1sV6yH0pL8' \
  -H 'Content-Type: application/json' \
  -d '{
    "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"]
  }'
{
  "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.",
  "responses": [],
  "created_at": "2026-09-30T10:04:18Z",
  "updated_at": "2026-09-30T10:04:18Z"
}

We fill the rest of the record the company needs from the order and from your credential, so there is nothing else to send. If the order has no loan number, send loan.number on the order first.

A request starts at submitted, because many companies review it before it reaches the appraiser. It moves to accepted when it is with the appraiser, to declined when the company does not take it forward, and to completed once a revised report has been delivered against it. Read GET /orders/{id}/revision-requests for the thread, and watch order.revision_requested and order.revision_responded.

A revised report arrives as order.completed with "revision": true, and the order lands at revised_report_complete.

6. Due dates and fees

Due dates. A due date you send on POST /orders is what the lender needs. A due date you send on PATCH /orders/{id} is a REQUEST. The date on the order changes only when the appraisal management company accepts it, and you learn the outcome from order.due_date_changed:

{
  "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"
  }
}

requested_by is lender for a change you asked for and company for one the appraisal management company made. The date can also move without a request from you, for example when an appointment cannot be kept. Always take the date from the order or the event, never from your own request.

Fees. The fee is read only through the API. fees.appraisal_fee is the fee the lender is charged, and 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. Either way, a later change raises order.fee_changed with the old and the new amount. There is no endpoint for objecting to a fee or proposing another one: send a message on the order with POST /orders/{order_id}/messages, and the company answers there.

What else you may amend. Some companies do not let a lender amend an order at all. Then PATCH is refused with 403 and code action_not_permitted_for_client, and the way to ask is a message on the order.

PATCH /orders/{id} accepts your own reference, the loan number, the client and investor, the contacts and parties, the notes, the appraiser instructions, and a due date request. An order carries one note of each type, and a note you send is added to the note of that type rather than replacing it; notes have no ids and cannot be edited or removed here. The property, the borrower names, the order type, the loan type and the add-ons cannot change once an order exists: cancel and place a new order instead. Amending a closed order is refused with 409.

7. Messages

curl -s -X POST https://api.appraisalhost.com/v1/orders/ord_9TBK4C2QFA7M/messages \
  -H 'Authorization: Bearer aht_at_7Qk2rX9wTm4ZbN1sV6yH0pL8' \
  -H 'Content-Type: application/json' \
  -d '{
    "recipient": "manager",
    "subject": "Access arrangements",
    "body": "The listing agent will meet the appraiser on site."
  }'
  • recipient on a message you send is manager (the appraisal management company) or appraiser.
  • A company that keeps appraiser contact in its own hands refuses appraiser with 422 and code recipient_not_allowed. Send it to manager instead.
  • On a message you read, recipient may also be lender: that is a message addressed to you. Accept all three values.
  • Attach a file by uploading it first and quoting its id in document_ids. A message from the company or the appraiser may carry documents of its own, in attachments; they are on the order as well.
  • GET /orders/{order_id}/messages returns the thread the lender is party to, oldest first. Internal notes between the company and the appraiser are not included.
  • A reply from the company or the appraiser raises order.message_posted. Your own messages do not.

8. Supporting documents

Upload the purchase and sale contract, an engagement letter, comparable sales, or anything else the appraiser needs. A document you upload is visible to the appraisal management company and to the assigned appraiser.

curl -s -X POST https://api.appraisalhost.com/v1/orders/ord_9TBK4C2QFA7M/documents \
  -H 'Authorization: Bearer aht_at_7Qk2rX9wTm4ZbN1sV6yH0pL8' \
  -F 'kind=supporting' \
  -F 'purpose=sales_contract' \
  -F 'description=Purchase and sale contract' \
  -F 'file=@purchase_and_sale.pdf'
{
  "id": "doc_2KM7Q0VZTC93",
  "kind": "supporting",
  "filename": "purchase_and_sale.pdf",
  "content_type": "application/pdf",
  "size_bytes": 412998,
  "created_at": "2026-09-17T14:40:11Z"
}
  • 25 MB per file. A larger file is refused with 413.
  • PDF, JPEG, PNG, TIFF, ZIP, plain text, XML and the common office document types are accepted. 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.
  • purpose is optional and says what the file is: engagement_letter, sales_contract, prior_report or other. Leave it out and other is assumed.
  • Small files can also ride along on POST /orders in the documents array, base64 encoded. Prefer the upload endpoint for anything over a megabyte or two.

9. Receiving the finished report

When the report is delivered, the order moves to report_complete and order.completed fires with every delivered file listed. Each file is a separate document with its own kind and its own id.

{
  "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" }
    ]
  }
}

Which documents arrive

kinduad_2_6uad_3_6What it is
report_pdfYesYesThe appraisal report as a PDF.
report_dataYes, an XML fileYes, a package in ZIP formThe report data. This is the one file whose form differs between the two standards.
invoiceWhen the company invoices through the platformWhen the company invoices through the platformThe invoice for the order. Always its own file.
compliance_certificateWhen the company issues oneWhen the company issues oneThe compliance certificate.
borrower_certificateWhen the company issues oneWhen the company issues oneThe borrower delivery certificate.
ssrWhen the order goes through a collateral delivery portalWhen the order goes through a collateral delivery portalA submission summary report. There may be more than one.
review_reportWhen the company's review process produces oneWhen the company's review process produces oneA 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.
supportingEither side, any timeEither side, any timeAnything supplied to support the order.

The rule to build against: the package replaces the report data file and nothing else. On the current standard the report data arrives as a ZIP package, and the invoice, the certificates and every other delivery document remain separate files exactly as they are on the prior standard. Do not unpack the ZIP looking for an invoice.

Downloading

List the documents on the order:

curl -s https://api.appraisalhost.com/v1/orders/ord_9TBK4C2QFA7M/documents \
  -H 'Authorization: Bearer aht_at_7Qk2rX9wTm4ZbN1sV6yH0pL8'

Then ask for a link one document at a time:

curl -s https://api.appraisalhost.com/v1/documents/doc_5RJ2N7VKTB41 \
  -H 'Authorization: Bearer aht_at_7Qk2rX9wTm4ZbN1sV6yH0pL8'
{
  "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"
  }
}

Follow the link with a plain GET and no Authorization header: the signature in the link is the authorization. The expires value in the URL is the same instant as expires_at, in Unix seconds.

The link is valid for five minutes and may be used more than once inside that window. Fetch a fresh one when it expires rather than storing links, and store the bytes you downloaded rather than the URL.

A document you are not entitled to see returns 404, not 403, so that ids cannot be probed.

Later documents

Documents also arrive after delivery: a submission summary report once the collateral portal answers, a corrected invoice, a revised report. Each one raises order.document_added. Handle that event rather than assuming the file list is final at order.completed.

SandboxWebhooks
Appraisal Host - Appraisal Management Software for AMCs and Lenders

Platform

  • Features
  • Integrations
  • Pricing

Solutions

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

Resources

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

Company

  • About
  • Contact

Appraisal Host

1 Washington Mall #1105

Boston, MA 02108

© 2026 Appraisal Host

|Privacy Policy|Terms of Service|SMS Consent

appraisalhost.com is a service of Appraisal Host LLC.

Powered byOptiWork.ai