Skip to main content
All Docs
FeaturesPurple PepperUpdated April 7, 2026

Offer-to-Tenancy Conversion

Offer-to-Tenancy Conversion

When an offer reaches accepted status, you can convert it directly into a new tenancy without re-entering data. The system pre-populates a 5-stage wizard with all available information from the offer — applicant details, property info, landlord contacts, and the offered rent.

Prerequisites

  • The offer must have a status of accepted. The "Create Tenancy" option is not available for offers in any other status.

Starting the Conversion

  1. Open the offer detail page for an accepted offer.
  2. Click the "Create Tenancy" button in the page header (displayed in green).
  3. The conversion wizard opens as a modal overlay, pre-loaded with offer data.

Note: An info banner on the offer detail page also indicates when an offer is ready for tenancy conversion.


Wizard Stages

Stage 1 — Property

Confirms the property linked to the offer. Displayed details include:

  • Full address
  • Property type, number of bedrooms and bathrooms
  • Furnished / unfurnished status
  • Linked landlord information (if available)

If no property was associated with the original offer, a property search input is shown instead. Type an address, city, or postcode to find and select the correct property before proceeding.


Stage 2 — Occupants

Pre-fills contact details for the main tenant and landlord:

  • Tenant name and email — from the lead applicant on the offer
  • Landlord name and email — from the property's linked landlord record

All fields are editable. The following lead applicant information is shown as read-only context (it is not directly submitted but auto-populates the tenancy notes):

  • Phone number
  • Employment status and employer name
  • Annual income
  • Pets and smoking status
  • Adverse credit history

Joint applicants and guarantors linked to the offer are also listed here for reference.


Stage 3 — Term

Configures the tenancy term:

FieldDefaultNotes
Start dateTodayEditable
Contract length12 monthsEditable
Monthly rentOffered rentPre-filled; editable
NotesAuto-generatedIncludes employment, income, and joint applicant context from the offer

The computed end date updates in real time as you adjust the start date or contract length.


Stage 4 — Review

Displays a summary of all fields before submission, with a reference back to the source offer. Review all details and use the Back button to make corrections if needed.


Stage 5 — Complete

Shown after successful tenancy creation. The page auto-redirects to the new tenancy overview within 2 seconds. You can also navigate manually if needed.


What Happens in the Background

  • Calling the wizard triggers the offer.offerToTenancyDraft query, which reads the accepted offer and assembles a pre-populated draft. An audit event (offer.tenancy_draft_generated) is recorded at this point.
  • On submission, the existing tenancy.createLegacy mutation creates the tenancy record.
  • The offer detail view and the tenancy list are both refreshed automatically on success.
  • No new database tables are created — all data is sourced from the existing offers, applicants, guarantors, properties, and landlords tables.

Error Handling

  • If the offer is not in accepted status, the offerToTenancyDraft query returns an error and the wizard displays a descriptive message.
  • If offer data cannot be loaded for any other reason, an error screen is shown with the specific error message and a Close button.

API Reference

offer.offerToTenancyDraft

Type: Query

Input:

{
  offerId: string; // Must belong to the current organisation
}

Returns:

{
  propertyId: string | null;
  propertyAddress: string | null;
  branchId: string | null;
  property: {
    propertyType: string | null;
    bedrooms: number | null;
    bathrooms: number | null;
    furnished: boolean;
  } | null;
  tenantName: string | null;       // Lead applicant full name
  tenantEmail: string | null;      // Lead applicant email
  landlordName: string | null;     // From linked landlord record
  landlordEmail: string | null;
  monthlyRent: string | null;      // Offered rent
  leadApplicant: {
    employmentStatus: string | null;
    employerName: string | null;
    annualIncome: number | null;
    phone: string | null;
    pets: boolean | null;
    smoking: boolean | null;
    adverseCredit: boolean | null;
    // ...additional enrichment fields
  } | null;
  jointApplicants: Array<{
    firstName: string;
    lastName: string;
    // ...full applicant details
  }>;
  guarantors: Array<{
    // ...guarantor details linked to applicants
  }>;
}

Errors:

  • Throws if the offer does not have status === "accepted"
  • Throws if the offer does not belong to the current organisation