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

Offer Invitation & Digital Offer Submission

Offer Invitation & Digital Offer Submission

The offer invitation workflow allows agents to send a prospective tenant a secure, branded link to submit a rental offer online. No tenant account or login is required.


Overview

The workflow has three stages:

  1. Agent sends an invitation — the agent creates a tokenised invitation link tied to a specific property and dispatches a branded email to the prospective tenant.
  2. Tenant submits an offer — the tenant follows the link to a public form, fills in their details, and submits.
  3. Automatic processing — on submission, the offer transitions to with_agent, applicant records are created, and the agent is notified by email.

Stage 1: Sending an Invitation

An agent sends an invitation using the offer.sendInvitation mutation.

What happens internally:

  • A unique token (UUID-shortUUID, 44 chars) is generated and stored in the offer_invitation_tokens table.
  • The agency's branding (logo URL, primary colour, name) is denormalised onto the token record so the public form can render without making authenticated queries.
  • An Inngest event is dispatched to send the branded invitation email.

Token properties:

PropertyValue
FormatUUID-shortUUID (44 chars, URL-safe)
Expiry14 days from creation
Single-useYes — marked isUsed on first submission

Stage 2: The Public Offer Form

The tenant receives an email and follows the link to /offer/[token].

The form is publicly accessible (no login required) and renders the agency's branding from the token. The form collects the following information:

Personal Details

FieldRequired
First name
Last name
PhoneOptional
Date of birthOptional
Current addressOptional

Employment

FieldRequired
Employment status✅ (employed, self-employed, unemployed, student, retired, other)
Employer nameOptional
Annual incomeOptional

Household Details

FieldNotes
PetsToggle + free-text details
Adverse credit historyToggle + free-text details
SmokerToggle

Joint Applicants

  • Up to 5 joint applicants can be added.
  • Each joint applicant provides: first name, last name, email, phone, and relationship to the primary applicant.
  • Joint applicants with a first name, last name, and email are saved as applicants rows with role: "joint".

Offer Terms

FieldNotes
Proposed monthly rentOptional
Proposed move-in dateOptional
Additional notesFree text, for negotiation details

GDPR

A consent notice is displayed on the form. Data is stored with the orgId for tenant isolation.


Stage 3: Submission Processing

When the tenant submits the form, the following happens automatically:

  1. Token validation — the token is checked for expiry and isUsed status. Invalid or expired tokens return an error.
  2. Offer status transition — the offer moves from invitedwith_agent in one step.
  3. Applicant records created — the primary applicant and any valid joint applicants are saved to the database.
  4. Agent notification — the agent receives an email with a direct link to the submitted offer, dispatched via Inngest.
  5. Audit log — entries are written for both the invitation creation and the offer submission.
  6. Token marked used — the token's isUsed flag is set to true, preventing re-submission.

Error States

The public form handles the following error conditions gracefully:

ConditionDisplayed message
Token not found"This offer invitation link is invalid or has expired."
Token expired (>14 days)Same as above
Token already usedSame as above
Network/server errorError message from the server response

Technical Reference

tRPC Procedures

offer.sendInvitation (authenticated mutation)

  • Creates an invitation token and dispatches the invitation email via Inngest.

offerInvite.getSession (public query, token-authenticated)

  • Validates the token and returns agency branding + property address for form rendering.

offerInvite.submitOffer (public mutation, token-authenticated)

  • Accepts the full form payload, creates applicant records, transitions offer status, and triggers agent notification.

Inngest Functions

Function IDTriggerAction
offer-invitation-emailInvitation createdSends branded invitation email to the prospective tenant
offer-submitted-agent-notifyOffer submittedSends notification email to the agent with a link to the offer

Database Table: offer_invitation_tokens

ColumnDescription
tokenThe unique invitation token (primary key)
offerIdForeign key to the associated offer
expiresAtTimestamp 14 days after creation
isUsedBoolean flag, set to true after submission
Branding fieldsDenormalised agency name, logo URL, primary colour

Middleware

The /offer path is added to public routes in src/middleware.ts so the offer form is accessible without an authenticated session.