Webhooks

Agent webhooks are outbound POSTs from BOX to URLs stored on the agent (WebhookAddress). They carry a topic (or a KYC / report payload without one) and are retried if delivery fails. They are not registered through this API.

POST /Notifications is a different product: a negotiator-level callback with event codes 5, 11, 12, and 13, optional HMAC, and no retry. See Notifications.

Subscribe

Give Lettings Hub an HTTPS URL that accepts POST with Content-Type: application/json. Optionally a static header name and value (for example X-API-Key). There is no HMAC on this path.

Several URLs can be stored comma-separated. Each attempt POSTs the same body to every URL. Delivery counts as successful if any URL returns 2xx; the others are still called.

Reapit Connect onboarding can append the v2 webhook URL onto the agent record. Ask your account manager to enable WebhookEnabled and set the address if you are not on that path.

What to return

Return any 2xx as soon as you have accepted the body. BOX does not read the response body. Process heavy work asynchronously. Ignore unknown fields and unknown topics.

Anything other than 2xx (including 4xx) is a failure and is retried. Do not use 4xx expecting BOX to stop.

Delivery

The first send is attempted when the event is raised. If that fails, the payload is stored and a background sender retries it. The sender interval is a platform setting (about one minute in the current daemon). Records with retry state 0–14 are eligible: fifteen attempts in total, then the row is left and logged as permanently failed.

Duplicates can occur. Deduplicate on topic plus applicationRef and any stable ids inside data. For KYC use KYCid; for reports use URL or EntryType plus applicant ids.

Envelope

Most events include topic, applicationRef (the tenancy / application reference), optional data, and metadata: EntryType, CreationDate, ApplicationId, ApplicantId, ApplicationExternalReference, ApplicantExternalReference.

KYC status has no topic — look for KYCid and EntryType Status Update KYC. Report available sets EntryType Report Available plus ReportType and URL; because that payload is built on the applicant-status type, you will usually also see topic updateApplicant. Key off EntryType or URL, not topic alone.

Topics

Topic When
createNewTenancyA tenancy is created
addApplicantAn applicant is added
updateApplicantAn applicant’s status changes
updateApplicationStatusThe tenancy step changes
uploadReapitDocumentA document is ready (body includes base64 fileData)
prescribedInformationCompletedPrescribed information is completed
tenancyFinalisedThe tenancy is finalised
tenancyStartDateChangedStart date changes (yyyy-MM-dd)
addNoteA note or audit-trail line

Rent-increase and related topics also exist (rentIncreaseNoticeIssued, and similar). Ignore any topic you do not handle.

updateApplicationStatus

{
  "topic": "updateApplicationStatus",
  "applicationRef": "0013524",
  "applicationStatus": 4,
  "isPrescribedInformationRequired": true,
  "isPrescribedInformationCompleted": false,
  "isTenancyFinalised": false,
  "howWillSignApplicants": 1,
  "howWillSignAgentLandlord": 1,
  "EntryType": "Update Application Status"
}

applicationStatus is the tenancy step:

ValueStep
1Referencing in progress
2Referencing complete
3Tenants confirming preferences
4Awaiting tenancy agreement
5Awaiting tenant signing
6Awaiting landlord signing
7Awaiting agent signing
8Awaiting agent to confirm inventory
9Awaiting move-in meter readings
10Awaiting move-out meter readings
11Complete
12Tenancy archived

updateApplicant

data.applicantRef is the applicant reference. applicationStatus here is not the table above: it is 0 while the application is still starting, otherwise 1. When the applicant is completed, a full Applicant object may be included.

{
  "topic": "updateApplicant",
  "applicationRef": "0013524",
  "applicationStatus": 1,
  "Status": "References in Progress",
  "data": {
    "applicantRef": "s0013524",
    "applicantStatus": "References in Progress",
    "reportType": 3,
    "rentShare": 50.0
  },
  "EntryType": "Status Update"
}

addApplicant

Same data shape as above, plus reapitContactId (the applicant ExternalRef) and type (tenant / guarantor). applicationStatus on this topic is the tenancy step integer.

createNewTenancy

data.address is an object (addressLine1, town, postcode, …), not a single formatted string. data.applicants lists the people on the tenancy.

uploadReapitDocument

{
  "topic": "uploadReapitDocument",
  "applicationRef": "0013524",
  "data": {
    "documentType": "TenancyAgreement",
    "fileName": "Tenancy_Agreement.pdf",
    "fileData": "<base64>"
  },
  "EntryType": "Document available"
}

documentType includes tenancy agreement, audit trail, how-to-rent, inventory, EPC, electrical certificates, KYC reports, rent-increase notices, and Other. Cap your JSON parser; the file can be large.

KYC (no topic)

{
  "Status": 3,
  "KYCid": "445566",
  "UserType": 1,
  "Email": "applicant@example.com",
  "Reports": {
    "1": "https://pre-prod.lettingshub.co.uk/webapi/v2/KYC/Report/445566/1"
  },
  "EntryType": "Status Update KYC"
}

Reports is only present when the check is complete. Keys are report-type integers (identity, Right to Rent, AML, PEPs).

Report available

{
  "ReportType": 2,
  "applicationRef": "0013524",
  "URL": "https://pre-prod.lettingshub.co.uk/webapi/v2/Applications/0013524/s0013524/Reports/2",
  "EntryType": "Report Available"
}

Fetch the PDF with that URL (and your Token header). The same POST may also include topic updateApplicant and data.

Other topics

prescribedInformationCompleted includes isTenancyFinalised. tenancyFinalised includes hasInventory, daysToReportIssues, and the prescribed-information flags. tenancyStartDateChanged sends oldStartDate and newStartDate. addNote sends data.typeId (usually MI) and data.description.

Example receiver

curl -X POST "https://crm.example/webhooks/box" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: <shared-secret>" \
  -d '{"topic":"updateApplicationStatus","applicationRef":"0013524","applicationStatus":4}'

Dispatch on topic when present, else on KYCid / EntryType. Return 204.