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 |
|---|---|
createNewTenancy | A tenancy is created |
addApplicant | An applicant is added |
updateApplicant | An applicant’s status changes |
updateApplicationStatus | The tenancy step changes |
uploadReapitDocument | A document is ready (body includes base64 fileData) |
prescribedInformationCompleted | Prescribed information is completed |
tenancyFinalised | The tenancy is finalised |
tenancyStartDateChanged | Start date changes (yyyy-MM-dd) |
addNote | A 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:
| Value | Step |
|---|---|
| 1 | Referencing in progress |
| 2 | Referencing complete |
| 3 | Tenants confirming preferences |
| 4 | Awaiting tenancy agreement |
| 5 | Awaiting tenant signing |
| 6 | Awaiting landlord signing |
| 7 | Awaiting agent signing |
| 8 | Awaiting agent to confirm inventory |
| 9 | Awaiting move-in meter readings |
| 10 | Awaiting move-out meter readings |
| 11 | Complete |
| 12 | Tenancy 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.