API Documentation

Access your property intelligence data programmatically. The RealiQ REST API is available on the Enterprise plan.

Authentication

All API requests require an API key passed via the Authorization header. API keys can be created and managed from Settings > API Keys in your dashboard.

curl -H "Authorization: Bearer nc_live_abc123..." \
  https://www.realiq.uk/api/v1/properties

API keys start with nc_ and are hashed with SHA-256 before storage. Keep your keys secret.

Rate Limiting

Each API key is limited to 1,000 requests per day. When exceeded, the API returns a 429 Too Many Requests response. Rate limit counters reset at midnight UTC.

Response Format

All responses use a standard JSON envelope.

Success (list)

{
  "data": [ ... ],
  "meta": {
    "count": 50,
    "has_more": true,
    "cursor": "eyJpZCI6IjUwIn0"
  }
}

Success (single)

{
  "data": { ... }
}

Error

{
  "error": {
    "message": "Invalid API key",
    "code": "UNAUTHORIZED"
  }
}

Pagination

List endpoints support cursor-based pagination. Pass cursor and optional limit (default 50, max 100).

GET /api/v1/properties?limit=25&cursor=eyJpZCI6IjI1In0

Endpoints

GET/api/v1/properties

List properties with optional filters.

Query Parameters

ParameterTypeDescription
sectorstringFilter by sector (e.g. Office, Industrial, Industrial Open Storage, Retail)
citystringFilter by city name
postcodestringFilter by postcode prefix
min_pricenumberMinimum asking price
max_pricenumberMaximum asking price
curl -H "Authorization: Bearer nc_live_abc123..." \
  "https://www.realiq.uk/api/v1/properties?sector=Industrial&limit=10"

Example Response

{
  "data": [
    {
      "id": "a1b2c3d4-...",
      "name": "Apex Business Park",
      "address": "Unit 5, Apex Park, Leeds LS11 5QA",
      "sector": "Industrial",
      "asking_price": 4250000,
      "niy": 6.85,
      "total_rent": 291125,
      "number_of_tenants": 3,
      "wault": 5.2,
      "created_at": "2026-02-10T14:30:00Z"
    }
  ],
  "meta": { "count": 1, "has_more": false, "cursor": null }
}

GET/api/v1/properties/:id

Get a single property with its tenancy schedule.

curl -H "Authorization: Bearer nc_live_abc123..." \
  "https://www.realiq.uk/api/v1/properties/a1b2c3d4-..."

PATCH/api/v1/properties/:id

Set sale status and sale evidence, edit Deal Tracker notes, or requote. Send only the fields you want to change; an explicit null clears a field. A status-only sale is allowed: sale_status of sold with no price records the sale and creates a comparable only once a real price and date exist. Legal moves are for_sale to under_offer, sold or withdrawn; under_offer to for_sale, sold or withdrawn; sold back to for_sale (undo); withdrawn back to for_sale. Requires write scope.

Fields

FieldTypeNotes
sale_statusstringfor_sale, under_offer, sold, withdrawn
sold_pricenumber | nullGBP. Optional even when sold
sale_dateYYYY-MM-DD | nullOptional even when sold
purchaser_investor_iduuid | nullMust be an investor in your workspace
acquisition_typestringinvestment or vacant_possession
guide_pricenumber | nullRequote. Matches are not recomputed; re-run matching afterwards
net_initial_yieldnumber | nullRequote, as a percentage
notes / notes_appendstringnotes_append is atomic; notes replaces and needs expected_updated_at
strike_price, expected_updated_atnumber, stringInternal target price; version token for optimistic concurrency (409 on conflict)
# Status-only sale: the agent confirmed it sold but not for how much
curl -X PATCH -H "Authorization: Bearer nc_..." -H "Content-Type: application/json" \
  -d '{"sale_status": "sold"}' \
  https://www.realiq.uk/api/v1/properties/a1b2c3d4-...

# Requote after an audit
curl -X PATCH -H "Authorization: Bearer nc_..." -H "Content-Type: application/json" \
  -d '{"guide_price": 2850000, "net_initial_yield": 6.75}' \
  https://www.realiq.uk/api/v1/properties/a1b2c3d4-...

GET/api/v1/matches

List investor-property matches with scores and AI commentary.

Query Parameters

ParameterTypeDescription
statusstringFilter by status: new, reviewed, contacted, passed
min_scorenumberMinimum match score (0-100)
investor_iduuidFilter matches for a specific investor
curl -H "Authorization: Bearer nc_live_abc123..." \
  "https://www.realiq.uk/api/v1/matches?min_score=90&status=new"

GET/api/v1/comparables

List comparable transactions from your evidence database.

Query Parameters

ParameterTypeDescription
sectorstringFilter by sector
citystringFilter by city
start_datedateTransaction date from (YYYY-MM-DD)
end_datedateTransaction date to (YYYY-MM-DD)
curl -H "Authorization: Bearer nc_live_abc123..." \
  "https://www.realiq.uk/api/v1/comparables?sector=Office&city=Manchester"

GET/api/v1/investors

List investors with their acquisition profiles.

Query Parameters

ParameterTypeDescription
namestringSearch by investor name
typestringFilter by investor type
curl -H "Authorization: Bearer nc_live_abc123..." \
  "https://www.realiq.uk/api/v1/investors?type=fund"

GET/api/v1/investors/:id

Get a single investor with all their acquisition requirements.

curl -H "Authorization: Bearer nc_live_abc123..." \
  "https://www.realiq.uk/api/v1/investors/e5f6g7h8-..."

PATCH/api/v1/investors/:id

Update an investor: send any of name, type, notes or active. Types are Institution, Private, REIT, Fund, Family Office, Prop Co or Other. Requires a key with write scope.

curl -X PATCH \
  -H "Authorization: Bearer nc_..." \
  -H "Content-Type: application/json" \
  -d '{"type": "Prop Co", "notes": "Trading co, off-market only"}' \
  https://www.realiq.uk/api/v1/investors/e5f6g7h8-...

GETPOST/api/v1/investors/:id/contacts

List an investor's contacts, or add one. POST takes name (required), email, phone, role and is_primary; setting is_primary demotes any existing primary. POST requires write scope.

curl -X POST \
  -H "Authorization: Bearer nc_..." \
  -H "Content-Type: application/json" \
  -d '{"name": "Jane Doe", "email": "jane@fund.com", "role": "Head of Acquisitions", "is_primary": true}' \
  https://www.realiq.uk/api/v1/investors/e5f6g7h8-.../contacts

PATCHDELETE/api/v1/investors/:id/contacts/:contactId

Correct a contact or remove one when they leave the firm. PATCH takes any of name, email, phone, role, notes and is_primary; pass null to clear a field, and setting is_primary demotes any existing primary. DELETE reports whether the contact was the primary, so you know the investor is left without one. Both require write scope.

curl -X PATCH \
  -H "Authorization: Bearer nc_..." \
  -H "Content-Type: application/json" \
  -d '{"role": "Partner", "phone": null}' \
  https://www.realiq.uk/api/v1/investors/e5f6g7h8-.../contacts/c1d2e3f4-...

curl -X DELETE \
  -H "Authorization: Bearer nc_..." \
  https://www.realiq.uk/api/v1/investors/e5f6g7h8-.../contacts/c1d2e3f4-...

GETPATCH/api/v1/requirements/:id

Read or update an acquisition mandate. PATCH accepts name, sectors, locations, min_lot_size, max_lot_size, min_yield, max_yield, min_wault_years, tenant_covenant_min (A/B/C), return_criteria_list, notes, is_hot and active. Re-run matching afterwards to rescore. Requires write scope.

curl -X PATCH \
  -H "Authorization: Bearer nc_..." \
  -H "Content-Type: application/json" \
  -d '{"sectors": ["Multi-Let Industrial"], "min_yield": 6.5, "return_criteria_list": ["Core Plus", "Value-Add"]}' \
  https://www.realiq.uk/api/v1/requirements/a1b2c3d4-...

GET/api/v1/tenancies

List tenancies across all properties.

Query Parameters

ParameterTypeDescription
property_iduuidFilter tenancies for a specific property
tenant_namestringSearch by tenant name
curl -H "Authorization: Bearer nc_live_abc123..." \
  "https://www.realiq.uk/api/v1/tenancies?tenant_name=Amazon"

GET/api/v1/stats

Get portfolio overview statistics.

curl -H "Authorization: Bearer nc_live_abc123..." \
  "https://www.realiq.uk/api/v1/stats"

Example Response

{
  "data": {
    "properties_count": 188,
    "total_value": 1510000000,
    "total_rent": 104100000,
    "investors_count": 109,
    "matches_count": 12120,
    "comparables_count": 923,
    "sector_breakdown": {
      "Industrial": 72,
      "Office": 48,
      "Retail": 35,
      "Mixed Use": 18,
      "Other": 15
    }
  }
}

POST/api/v1/extract

Run AI extraction on a document (PDF, DOCX or XLSX). Requires a key with write scope. Results that pass validation are committed to the portfolio and matched automatically. Flagged results remain in pending review. Pass auto_commit=false or review_required=true to require review for every result.

Direct file upload

PDFs are accepted up to 20MB. DOCX and XLSX files are accepted up to 50MB and converted to text before extraction.

curl -X POST \
  -H "Authorization: Bearer nc_..." \
  -F "file=@brochure.pdf" \
  https://www.realiq.uk/api/v1/extract

Upload to storage, then extract

For batch workflows, upload each source straight to private storage and extract it by reference. The same 20MB PDF and 50MB DOCX/XLSX extraction limits apply. Three steps: get a signed URL, PUT the file to it, then call extract with the returned storage_path.

# 1. Get a signed upload URL
curl -X POST \
  -H "Authorization: Bearer nc_..." \
  -H "Content-Type: application/json" \
  -d '{"filename": "big-brochure.pdf"}' \
  https://www.realiq.uk/api/v1/uploads
# -> { "data": { "upload_url": "https://...", "storage_path": "<org>/api/..." } }

# 2. PUT the file straight to storage
curl -X PUT --data-binary @big-brochure.pdf \
  -H "Content-Type: application/pdf" \
  "<upload_url from step 1>"

# 3. Run extraction on the uploaded file
curl -X POST \
  -H "Authorization: Bearer nc_..." \
  -H "Content-Type: application/json" \
  -d '{"storage_path": "<storage_path from step 1>"}' \
  https://www.realiq.uk/api/v1/extract

Extract supplied text

Send 50 to 200,000 characters when your own pipeline has already extracted the document body. RealiQ retains the submitted text as the source record.

curl -X POST \
  -H "Authorization: Bearer nc_..." \
  -H "Content-Type: application/json" \
  -d '{"filename":"deal-email.eml","document_type":"brochure","text":"<full document text>"}' \
  https://www.realiq.uk/api/v1/extract

To backfill a whole folder, see scripts/bulk-upload.py, which loops these three steps over every document.

Example Response

{
  "data": {
    "extraction_id": "f1a2b3c4-...",
    "property": {
      "name": "Phoenix House",
      "address": "45 High Street, Birmingham B2 4LP",
      "sector": "Office",
      "asking_price": 3750000,
      "niy": 7.2
    },
    "tenancies_count": 4,
    "comparables_count": 2,
    "validation": {
      "score": 87,
      "status": "passed"
    },
    "status": "completed",
    "commit_outcome": {
      "requested": true,
      "performed": true,
      "outcome": "saved",
      "property_id": "a1b2c3d4-..."
    }
  }
}

GET/api/v1/extractions

List your extractions. Defaults to status=pending_review (documents extracted but not yet committed to the portfolio). Cursor-paginated.

curl -H "Authorization: Bearer nc_..." \
  "https://www.realiq.uk/api/v1/extractions?status=pending_review&limit=100"

GET/api/v1/extractions/:id

Retrieve the complete structured result, validation record, commit state and source-file availability for one organisation-scoped extraction.

curl -H "Authorization: Bearer nc_..." \
  "https://www.realiq.uk/api/v1/extractions/<extraction_id>"

POST/api/v1/extractions/commit

Commit pending-review extractions to your portfolio (properties, tenancies and comparables) in bulk, for legacy or deliberately reviewed workflows. With no body it commits the next validation-passed batch of up to 50. Pass extraction_ids to commit specific reviewed results, including flagged ones. Runs without AI matching by default to keep it fast; pass match: true to score as you commit, or Run Matching in the app afterwards. Loop while meta.has_more is true. Requires write scope.

curl -X POST \
  -H "Authorization: Bearer nc_..." \
  -H "Content-Type: application/json" \
  -d '{"match": false}' \
  https://www.realiq.uk/api/v1/extractions/commit
# -> { "data": [ { "extraction_id": "...", "outcome": "saved", "property_id": "...", "comparables_inserted": 3 }, ... ],
#      "meta": { "count": 50, "has_more": true } }