Skip to main content
All endpoints require a valid Bearer token. State-mutating requests must include a csrf_token — obtain one from GET /api/security/csrf-token.
Tenant contact fields (tenant_name, tenant_email, tenant_number_primary, tenant_number_work) are encrypted at rest using XSalsa20-Poly1305. They are transparently decrypted in API responses. A plaintext search index is maintained alongside encrypted data to support name-based searches without decrypting every row.

Tenants

List tenants

GET /api/tenants/manage?action=list Returns a paginated list of tenant records. Required permission: api.tenants.manage.manage
action
string
required
Must be list.
Search by tenant name.
address_id
integer
Filter tenants assigned to a specific property address.
active
boolean
true returns only active tenants; false returns inactive.
unassigned
boolean
Set to true to return tenants not currently assigned to a property.
limit
integer
default:"50"
Maximum records to return (max 200).
offset
integer
default:"0"
Number of records to skip.
curl -X GET "https://propops.yourcompany.com/api/tenants/manage?action=list&search=Smith&limit=20" \
  -H "Authorization: Bearer <token>"
{
  "success": true,
  "data": [
    {
      "ID": 100,
      "uuid": "990e8400-e29b-41d4-a716-446655440001",
      "tenant_name": "Tenant_001",
      "tenant_email": "tenant001@example.com",
      "tenant_number_primary": "07700000003",
      "tenant_number_work": "01200000002",
      "address_id": 5,
      "full_address": "1 Example Street, Sample Town, EX1 1AA",
      "created_at": "2024-01-10T08:00:00Z"
    }
  ],
  "count": 80,
  "message": "Operation completed successfully"
}

Get a single tenant

GET /api/tenants/manage?action=get&uuid=<uuid>
action
string
required
Must be get.
uuid
string
required
Tenant UUID.

Create a tenant

POST /api/tenants/manage Required permission: api.tenants.manage.manage
tenant_name
string
required
Full name of the tenant. Encrypted at rest.
tenant_email
string
Tenant email address. Encrypted at rest.
tenant_number_primary
string
Primary phone number. Encrypted at rest.
tenant_number_work
string
Work phone number. Encrypted at rest.
tenant_address_id
integer
ID of the property address to assign the tenant to.
csrf_token
string
required
CSRF token.
curl -X POST "https://propops.yourcompany.com/api/tenants/manage" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"tenant_name":"Jane Smith","tenant_email":"jane.smith@example.com","tenant_number_primary":"07712345678","tenant_address_id":5,"csrf_token":"<csrf-token>"}'
{
  "success": true,
  "tenant_id": 101,
  "tenant_uuid": "990e8400-e29b-41d4-a716-446655440002",
  "message": "Tenant created successfully"
}

Update a tenant

PUT /api/tenants/manage Update one or more fields on an existing tenant record.
uuid
string
required
UUID of the tenant to update.
csrf_token
string
required
CSRF token.
All create-time fields are accepted as optional update fields.

Delete a tenant

DELETE /api/tenants/manage Removes a tenant record. Before deleting, confirm the tenant has no active job associations.
uuid
string
required
UUID of the tenant to delete.
csrf_token
string
required
CSRF token.

GDPR Data Export

This endpoint satisfies the UK GDPR right of access (Article 15 UK GDPR, Data Protection Act 2018). Use it when a tenant submits a Subject Access Request (SAR). The export includes all personal data held for that individual. Every call is recorded in the audit trail.

Export GDPR report

GET /api/tenants/gdpr-report Exports a complete, portable report of all personal data held for a tenant. The response includes data from every relevant table — contact details, addresses, job history, case note references, consent records, and activity logs. Required permission: api.tenants.gdpr_report.view (staff only)
tenant_uuid
string
required
UUID of the tenant to export data for.
curl -X GET "https://propops.yourcompany.com/api/tenants/gdpr-report?tenant_uuid=990e8400-e29b-41d4-a716-446655440001" \
  -H "Authorization: Bearer <token>"
{
  "success": true,
  "data": {
    "generated_at": "2024-06-15T10:30:00Z",
    "generated_by": "Staff_001",
    "subject": {
      "uuid": "990e8400-e29b-41d4-a716-446655440001",
      "tenant_name": "Jane Smith",
      "tenant_email": "jane.smith@example.com",
      "tenant_number_primary": "07712345678",
      "tenant_number_work": null
    },
    "addresses": [
      {
        "address_line1": "1 Example Street",
        "address_line2": "Flat A",
        "city": "Sample Town",
        "postcode": "EX1 1AA",
        "country": "United Kingdom"
      }
    ],
    "jobs": [
      {
        "job_ref": "JOB-001",
        "job_title": "Boiler Service - Unit 001",
        "status": "Completed",
        "date_created": "2024-01-15",
        "date_completed": "2024-06-02"
      }
    ],
    "consent_records": [
      {
        "consent_version": "1.2",
        "consented_at": "2024-01-10T08:00:00Z",
        "ip_fingerprint": "203.0.113.xxx"
      }
    ],
    "activity_log_entries": 14
  },
  "message": "GDPR report generated successfully"
}

POST /api/gdpr/consent Records a versioned consent entry. Use this when a tenant or landlord accepts your terms of service, privacy policy, or a specific data processing activity. Each entry stores a timestamp, the policy version, and an IP fingerprint.
user_uuid
string
required
UUID of the user giving consent.
The type of consent being recorded (e.g. privacy_policy, terms_of_service, marketing).
The version of the document being consented to (e.g. 1.2).
csrf_token
string
required
CSRF token.
curl -X POST "https://propops.yourcompany.com/api/gdpr/consent" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"user_uuid":"990e8400-e29b-41d4-a716-446655440001","consent_type":"privacy_policy","consent_version":"1.2","csrf_token":"<csrf-token>"}'
{
  "success": true,
  "message": "Consent recorded successfully"
}
GET /api/gdpr/consent Returns all consent records for a user, ordered by most recent first. Useful for auditing and subject access responses. Required permission: Staff account required.
user_uuid
string
required
UUID of the user whose consent records to retrieve.
curl -X GET "https://propops.yourcompany.com/api/gdpr/consent?user_uuid=990e8400-e29b-41d4-a716-446655440001" \
  -H "Authorization: Bearer <token>"
{
  "success": true,
  "data": [
    {
      "ID": 1,
      "user_uuid": "990e8400-e29b-41d4-a716-446655440001",
      "consent_type": "privacy_policy",
      "consent_version": "1.2",
      "consented_at": "2024-01-10T08:00:00Z",
      "ip_fingerprint": "203.0.113.xxx"
    },
    {
      "ID": 2,
      "user_uuid": "990e8400-e29b-41d4-a716-446655440001",
      "consent_type": "terms_of_service",
      "consent_version": "2.0",
      "consented_at": "2024-01-10T08:01:00Z",
      "ip_fingerprint": "203.0.113.xxx"
    }
  ],
  "count": 2,
  "message": "Operation completed successfully"
}

Tenant List (Lightweight)

The /api/tenants/list endpoint is a lighter-weight alternative to /api/tenants/manage designed for dropdown population and job assignment workflows. It returns the same tenant data with support for list, get, and create actions.

List tenants for assignment

GET /api/tenants/list?action=list Returns tenants suitable for assignment to jobs or addresses. Supports filtering by address, search term, active state, and unassigned status. Required permission: api.tenants.list.manage
action
string
required
Must be list.
search
string
Search by tenant name, email, or phone number.
address_id
integer
Filter tenants assigned to a specific address. Also includes unassigned tenants in the results.
unassigned
boolean
Set to true to return only tenants not currently assigned to any address.
active
integer
1 for active tenants, 0 for inactive.
limit
integer
default:"50"
Maximum records to return (max 1000).
offset
integer
default:"0"
Number of records to skip.
curl -X GET "https://propops.yourcompany.com/api/tenants/list?action=list&search=Smith&unassigned=true" \
  -H "Authorization: Bearer <token>"
{
  "success": true,
  "data": [
    {
      "ID": 100,
      "uuid": "990e8400-e29b-41d4-a716-446655440001",
      "tenant_name": "Tenant_001",
      "tenant_email": "tenant001@example.com",
      "tenant_number_primary": "07700000003",
      "tenant_number_work": "01200000002",
      "full_address": ""
    }
  ],
  "count": 1
}

Get a tenant by ID

GET /api/tenants/list?action=get&id=<id> Returns a single tenant record by numeric ID. Required permission: api.tenants.list.manage
action
string
required
Must be get.
id
integer
required
Numeric ID of the tenant to retrieve.

Create a tenant (lightweight)

POST /api/tenants/list with action=create Creates a new tenant record. Equivalent to POST /api/tenants/manage but routed through the list endpoint. Required permission: api.tenants.list.manage
Requires CSRF token.
action
string
required
Must be create.
tenant_name
string
required
Full name of the tenant. Encrypted at rest.
tenant_email
string
Email address. Encrypted at rest.
tenant_number_primary
string
Primary phone number. Encrypted at rest.
tenant_number_work
string
Work phone number. Encrypted at rest.
tenant_address_id
integer
ID of the property address to assign the tenant to.
csrf_token
string
required
CSRF token from GET /api/security/csrf-token.
curl -X POST "https://propops.yourcompany.com/api/tenants/list" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d 'action=create&tenant_name=Jane+Smith&tenant_email=jane.smith@example.com&tenant_number_primary=07712345678&tenant_address_id=5&csrf_token=<csrf-token>'
{
  "success": true,
  "tenant_id": 101,
  "tenant_uuid": "990e8400-e29b-41d4-a716-446655440002",
  "message": "Tenant created successfully"
}

Assign Address

Assign a tenant to an address

POST /api/tenants/assign-address Assigns or moves a tenant to a specific property address. Updates the tenant’s tenant_address_id field. If the tenant was previously assigned to another address, this replaces that assignment. Required permission: api.tenants.assign_address.manage
Requires CSRF token.
tenant_id
integer
required
Numeric ID of the tenant to reassign.
address_id
integer
required
Numeric ID of the target property address.
csrf_token
string
required
CSRF token from GET /api/security/csrf-token.
curl -X POST "https://propops.yourcompany.com/api/tenants/assign-address" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d 'tenant_id=100&address_id=12&csrf_token=<csrf-token>'
{
  "success": true,
  "message": "Tenant assigned to address successfully",
  "full_address": "12 Elm Road, London, EC1A 1BB"
}
Error — tenant not found:
{
  "success": false,
  "error": "Tenant not found"
}
Error — address not found:
{
  "success": false,
  "error": "Address not found"
}