For App Developers

Build on the property record.

The Foundation API lets your software submit property service events, attach documents, and read event history — programmatically, at scale. Your field software, CRM, or dispatching platform can contribute directly to the permanent property record.

Base URL

https://api.foundation-dev.bluetruss.com

Source: PUBLIC_API_BASE_URL

Authentication

Pass your provider identity via the X-Provider-Id request header. API keys will be issued during early access onboarding.

Format

All request and response bodies are JSON unless uploading a document, which uses multipart/form-data. All timestamps are ISO 8601 with timezone offset.

API Reference — v0.0.1

Endpoints

Endpoints for submitting, retrieving, and browsing provider-scoped property events. Use the read patterns below to choose the right route for your workflow.

Read Patterns

  • Use GET /events for paginated list views of your own submitted events.
  • Use GET /sites/{siteId}/events for property timelines with cross-provider entries redacted.
  • Use GET /events/by-provider-event-id/{providerEventId} when your system key is providerEventId.
  • Use GET /events/{eventId} when you already have the Foundation eventId.
  • Use GET /sites/search?query=... when you need to look up Foundation siteId values by address text or postal code across all sites.

Try It Defaults

Used for all Try It requests on this page.

Events

POST
/events

Submit a new property event

Records a completed service event against a property. The property is resolved automatically from the site address. Returns a unique eventId that can be used to attach documents.

X-Provider-Id = your-provider-id Content-Type = application/json

Request Body

{
  "providerEventId": "WO-10045",
  "eventType": "hvac.service.completed",
  "occurredAt": "2026-07-01T14:30:00-05:00",
  "summary": "Annual HVAC tune-up, replaced filter, checked refrigerant.",
  "site": {
    "addressLine1": "123 Main Street",
    "city": "Nashville",
    "state": "TN",
    "postalCode": "37201"
  },
  "tags": ["hvac", "maintenance"],
  "references": [
    { "type": "workOrder", "value": "WO-10045" }
  ],
  "metadata": {
    "technician": "Jane Doe",
    "unitModel": "Carrier 24ACC636A003"
  }
}

Responses

  • 202 Accepted Event recorded. Body contains eventId and providerEventId.
    {
      "eventId": "f4ca8a20-8f7b-4e67-9cb1-c07b68f9250b",
      "providerEventId": "WO-10045",
      "status": "accepted"
    }
  • 400 Bad Request Validation failed. Body contains field-level error details.
    {
      "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
      "title": "Validation failed.",
      "status": 400,
      "errors": {
        "ProviderEventId": ["ProviderEventId is required."],
        "Site.PostalCode": ["Site.PostalCode is required."]
      }
    }
  • 409 Conflict An event with this providerEventId already exists.
    {
      "message": "An event with this ProviderEventId already exists.",
      "providerEventId": "WO-10045",
      "eventId": "f4ca8a20-8f7b-4e67-9cb1-c07b68f9250b"
    }
GET
/events

List your submitted events

Returns a paginated list of events submitted by the provider identity in X-Provider-Id. Use page and pageSize to sync or audit your event stream.

X-Provider-Id = your-provider-id

Responses

  • 200 OK Paginated list returned with items and totalCount.
    {
      "page": 1,
      "pageSize": 25,
      "totalCount": 73,
      "items": [
        {
          "eventId": "f4ca8a20-8f7b-4e67-9cb1-c07b68f9250b",
          "providerEventId": "WO-10045",
          "eventType": "hvac.service.completed",
          "occurredDate": "2026-07-01T14:30:00-05:00",
          "summary": "Annual HVAC tune-up, replaced filter, checked refrigerant."
        }
      ]
    }
  • 400 Bad Request Pagination validation failed (page < 1 or pageSize outside 1-100).
    {
      "title": "Validation failed.",
      "status": 400,
      "errors": {
        "page": ["page must be greater than or equal to 1."],
        "pageSize": ["pageSize must be between 1 and 100."]
      }
    }
GET
/events/{eventId}

Retrieve an event by Foundation ID

Returns the full event record, metadata, and any attached documents. Only accessible to the provider that submitted the event.

X-Provider-Id = your-provider-id

Responses

  • 200 OK Event found. Body contains full event details and document list.
    {
      "eventId": "f4ca8a20-8f7b-4e67-9cb1-c07b68f9250b",
      "providerEventId": "WO-10045",
      "eventType": "hvac.service.completed",
      "occurredDate": "2026-07-01T14:30:00-05:00",
      "summary": "Annual HVAC tune-up, replaced filter, checked refrigerant.",
      "documents": []
    }
  • 404 Not Found Event not found or not accessible with the current provider identity.
    {
      "title": "Event not found.",
      "status": 404,
      "detail": "Event 'f4ca8a20-8f7b-4e67-9cb1-c07b68f9250b' was not found."
    }
PATCH
/events/{eventId}

Update an event

Partially updates a submitted event. Include only the fields you want to change — omitted fields are left unchanged. Only the submitting provider can update.

X-Provider-Id = your-provider-id Content-Type = application/json

Request Body

{
  "summary": "Updated summary text.",
  "eventType": "hvac.service.completed",
  "occurredAt": "2026-07-01T14:30:00-05:00",
  "tags": ["hvac", "maintenance"],
  "metadata": {
    "technician": "Jane Doe"
  }
}

Responses

  • 204 No Content Event updated successfully.
    // No response body.
  • 400 Bad Request Validation failed — unrecognized eventType value.
    {
      "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
      "title": "Validation failed.",
      "status": 400,
      "errors": {
        "EventType": ["EventType must be a recognized Foundation event type value."]
      }
    }
  • 404 Not Found Event not found or not accessible with the current provider identity.
    {
      "title": "Event not found.",
      "status": 404,
      "detail": "Event 'f4ca8a20-8f7b-4e67-9cb1-c07b68f9250b' was not found."
    }
DELETE
/events/{eventId}

Delete an event

Permanently removes an event. Only the provider that submitted the event can delete it.

X-Provider-Id = your-provider-id

Responses

  • 204 No Content Event deleted successfully.
    // No response body.
  • 404 Not Found Event not found or not accessible with the current provider identity.
    {
      "title": "Event not found.",
      "status": 404,
      "detail": "Event 'f4ca8a20-8f7b-4e67-9cb1-c07b68f9250b' was not found."
    }
GET
/events/types

Discover supported event types

Returns the current catalog of accepted eventType values. Use this endpoint to populate dropdowns and keep clients in sync without hard-coding.

Responses

  • 200 OK Catalog returned successfully.
    {
      "eventTypes": [
        "hvac.service.completed",
        "roof.replaced",
        "plumbing.repaired"
      ]
    }

Documents

POST
/events/{eventId}/documents

Attach a document to an event

Uploads a file (PDF, image) and attaches it to an existing event. Accepts multipart/form-data with a documentType field and a file field.

X-Provider-Id = your-provider-id Content-Type = multipart/form-data

Request Body

// multipart/form-data
documentType: "Invoice"   // Invoice | Receipt | Photo | Inspection Report | Permit | Warranty
file: <binary>

Responses

  • 202 Accepted Document uploaded and attached.
    {
      "documentId": "6d67bc57-6092-41e2-a43c-2d70a5efef2c",
      "eventId": "f4ca8a20-8f7b-4e67-9cb1-c07b68f9250b",
      "documentType": "Invoice",
      "status": "accepted"
    }
  • 400 Bad Request Validation failed — missing file, unsupported document type, or file is empty.
  • 404 Not Found Parent event not found.
  • 413 Payload Too Large File exceeds the 25 MB limit.
    {
      "message": "File size exceeds the 25 MB limit."
    }
  • 415 Unsupported Media Type MIME type not permitted for the chosen document type.
    {
      "message": "Unsupported MIME type 'text/plain' for document type 'Invoice'."
    }
  • 422 Unprocessable Entity Document limit reached (max 20 per event).
    {
      "message": "Document limit reached. Maximum 20 documents are allowed per event."
    }
GET
/events/{eventId}/documents

List documents attached to an event

Returns document metadata for a single event. Access is provider-scoped and only available to the provider that can access the event.

X-Provider-Id = your-provider-id

Responses

  • 200 OK Document list returned successfully.
    {
      "eventId": "f4ca8a20-8f7b-4e67-9cb1-c07b68f9250b",
      "totalCount": 2,
      "items": [
        {
          "documentId": "6d67bc57-6092-41e2-a43c-2d70a5efef2c",
          "documentType": "Invoice",
          "uploadDate": "2026-07-02T09:41:18.1129153+00:00",
          "downloadUrl": "/events/f4ca8a20-8f7b-4e67-9cb1-c07b68f9250b/documents/6d67bc57-6092-41e2-a43c-2d70a5efef2c"
        }
      ]
    }
  • 404 Not Found Event not found or not accessible with the current provider identity.
    {
      "message": "Event not found."
    }
GET
/events/{eventId}/documents/{documentId}

Download a document

Returns the raw file content of an attached document with appropriate Content-Type and Content-Disposition headers. Access is provider-scoped; X-Provider-Id must match the provider that created the event.

X-Provider-Id = your-provider-id

Responses

  • 200 OK File stream returned.
    // Binary file stream
    Content-Type: application/pdf
    Content-Disposition: attachment; filename="invoice-10045.pdf"
  • 404 Not Found Document not found, event not found, or the document is not accessible to this provider.
    {
      "message": "Document not found."
    }
DELETE
/events/{eventId}/documents/{documentId}

Delete a document

Permanently removes an attached document and its stored file. Access is provider-scoped; X-Provider-Id must match the provider that created the event.

X-Provider-Id = your-provider-id

Responses

  • 204 No Content Document deleted successfully.
    // No response body.
  • 404 Not Found Document not found, event not found, or the document is not accessible to this provider.
    {
      "message": "Document not found."
    }
GET
/events/documents/types

Discover supported document types

Returns the current catalog of accepted documentType values for document uploads.

Responses

  • 200 OK Document type catalog returned successfully.
    {
      "documentTypes": [
        "Invoice",
        "Receipt",
        "Photo",
        "Inspection Report",
        "Permit",
        "Warranty"
      ]
    }

Alternate

GET
/events/by-provider-event-id/{providerEventId}

Retrieve an event by your own ID

Looks up an event using the providerEventId you assigned at submission. Useful for checking whether a work order has already been recorded.

X-Provider-Id = your-provider-id

Responses

  • 200 OK Event found.
    {
      "eventId": "f4ca8a20-8f7b-4e67-9cb1-c07b68f9250b",
      "providerEventId": "WO-10045",
      "eventType": "hvac.service.completed",
      "occurredDate": "2026-07-01T14:30:00-05:00",
      "summary": "Annual HVAC tune-up, replaced filter, checked refrigerant.",
      "documents": []
    }
  • 404 Not Found No event found for this providerEventId.
    {
      "title": "Event not found.",
      "status": 404,
      "detail": "Event with providerEventId 'WO-10045' was not found."
    }

Sites

GET
/sites/search

Search sites to find Foundation site IDs

Searches all known sites by siteId, address, city, state, or postalCode and returns matching site records. Each result includes whether your provider has historical services at that site.

X-Provider-Id = your-provider-id

Responses

  • 200 OK Paginated matching sites returned.
    {
      "query": "123 main",
      "page": 1,
      "pageSize": 25,
      "totalCount": 2,
      "items": [
        {
          "siteId": "30000000-0000-0000-0000-000000000001",
          "addressLine1": "123 main st",
          "city": "nashville",
          "state": "tn",
          "postalCode": "37201",
          "hasProviderHistory": true
        },
        {
          "siteId": "30000000-0000-0000-0000-000000000004",
          "addressLine1": "900 main st",
          "city": "nashville",
          "state": "tn",
          "postalCode": "37209",
          "hasProviderHistory": false
        }
      ]
    }
  • 400 Bad Request Validation failed (query missing or pagination invalid).
    {
      "title": "Validation failed.",
      "status": 400,
      "errors": {
        "query": ["query is required."]
      }
    }
GET
/sites/{siteId}

Retrieve a site by Foundation ID

Returns the canonical site record for a property that has visible activity for the requesting provider.

X-Provider-Id = your-provider-id

Responses

  • 200 OK Site found.
    {
      "siteId": "30000000-0000-0000-0000-000000000001",
      "addressLine1": "1453 Maple Ridge Dr",
      "city": "Denver",
      "state": "CO",
      "postalCode": "80210"
    }
  • 404 Not Found Site not found or not visible to the current provider identity.
    {
      "title": "Site not found.",
      "status": 404,
      "detail": "Site '30000000-0000-0000-0000-000000000001' was not found."
    }
GET
/sites/{siteId}/events

List events for a specific property site

Returns a paginated site timeline for one siteId. Events from other providers are included with limited fields so provider ownership details remain private.

X-Provider-Id = your-provider-id

Responses

  • 200 OK Paginated site event list returned with items and totalCount.
    {
      "siteId": "30000000-0000-0000-0000-000000000001",
      "site": {
        "addressLine1": "1453 Maple Ridge Dr",
        "city": "Denver",
        "state": "CO",
        "postalCode": "80210"
      },
      "page": 1,
      "pageSize": 25,
      "totalCount": 2,
      "items": [
        {
          "eventId": "20000000-0000-0000-0000-000000000009",
          "providerEventId": "seed-frontrange-2025-001",
          "eventType": "roof.inspection.completed",
          "occurredDate": "2025-06-20T16:05:00+00:00",
          "summary": "Performed post-winter roof inspection and replaced damaged ridge cap shingles.",
          "visibility": "full"
        },
        {
          "eventId": "20000000-0000-0000-0000-000000000003",
          "providerEventId": null,
          "eventType": "roof.replaced",
          "occurredDate": "2024-09-22T13:45:00+00:00",
          "summary": null,
          "visibility": "limited"
        }
      ]
    }
  • 400 Bad Request Pagination validation failed (page < 1 or pageSize outside 1-100).
    {
      "title": "Validation failed.",
      "status": 400,
      "errors": {
        "page": ["page must be greater than or equal to 1."],
        "pageSize": ["pageSize must be between 1 and 100."]
      }
    }

Reference Data

Supported event types

The eventType field must be one of the recognized values below. For production integrations, discover values at runtime from GET /events/types and refresh your local cache periodically.

  • hvac.service.completed HVAC service
  • roof.replaced Roof replacement
  • plumbing.repaired Plumbing repair

Discovery — cURL

curl -X GET https://api.foundation-dev.bluetruss.com/events/types

Quick Start — cURL

curl -X POST https://api.foundation-dev.bluetruss.com/events \
  -H "Content-Type: application/json" \
  -H "X-Provider-Id: your-provider-id" \
  -d '{
    "providerEventId": "WO-10045",
    "eventType": "hvac.service.completed",
    "occurredAt": "2026-07-01T14:30:00-05:00",
    "summary": "Annual HVAC tune-up.",
    "site": {
      "addressLine1": "123 Main Street",
      "city": "Nashville",
      "state": "TN",
      "postalCode": "37201"
    }
  }'

Ready to integrate?

Foundation is in early access. Tell us about your platform and we'll get you set up with credentials and sandbox access.

Request API Access