TypeScript SDK

Type-safe client for the Model Match API with full IntelliSense support.

The Model Match TypeScript SDK gives you a fully typed client for every API resource. It handles authentication, request formatting, and response parsing — so you can focus on working with the data.

Installation

npm install @model-match/api

Setup

Create a client once at startup, passing your API key:

import { createClient } from "@model-match/api";

const client = createClient({ apiKey: process.env.MODEL_MATCH_API_KEY });

createClient configures a process-global client — call it once and every method call reuses it. The key is sent as x-api-key on every request.

The base URL defaults to https://api.modelmatch.com. Override it with the baseUrl option, or set the MMR_API_URL environment variable (the only env var the SDK reads automatically). For per-user / multi-tenant auth, build a per-call client with createApiClient(...) instead of the global singleton.

Querying Data

Every resource exposes two methods: .list() for filtered, paginated results and .get() for a single record by ID. Request options follow the hey-api convention — the request body goes under body, and path parameters go under path.

Listing Records

Pass the same filtering, sorting, and pagination options you'd use with the REST API, wrapped in body:

const result = await client.loans.list({
  body: {
    flatFilters: {
      state: "CA",
      transactionType: "purchase",
      mortgageAmount: { gte: 500000 },
    },
    sort: [{ field: "mortgageDate", order: "desc" }],
    pagination: { size: 50 },
  },
});

console.log(`Found ${result.data.total} loans`);
console.log(result.data.data); // LoanSummary[]

The response is the hey-api result object: result.data is the parsed response body, so the rows are result.data.data, the count is result.data.total, and the next-page cursor is result.data.cursor.

Getting a Single Record

Fetch the complete record for any entity by its ID, passed under path:

const loan = await client.loans.get({ path: { id: "LOAN_ID" } });
const originator = await client.originators.get({ path: { nmlsId: "NMLS_ID" } });
const agent = await client.agents.get({ path: { id: "AGENT_ID" } });

Detail responses include all nested data — buyers, sellers, agents, valuation history, and more — that list responses omit for performance.

Practical Examples

Find Top Producers in a Market

const topOriginators = await client.originators.list({
  body: {
    flatFilters: { state: "TX" },
    sort: [{ field: "totalVolume", order: "desc" }],
    period: "last12Months",
    pagination: { size: 25 },
  },
});

for (const originator of topOriginators.data.data) {
  console.log(`${originator.name} — $${originator.totalVolume}`);
}

Search Across All Entity Types

const searchResults = await client.search.instant({
  body: {
    query: "Wells Fargo",
    limit: 10,
  },
});

Paginate Through Large Datasets

const allLoans = [];
let cursor: string | undefined;

do {
  const page = await client.loans.list({
    body: {
      flatFilters: { state: "CA" },
      pagination: { size: 100, cursor },
    },
  });

  allLoans.push(...page.data.data);
  cursor = page.data.cursor;
} while (cursor);

console.log(`Collected ${allLoans.length} loans`);

Available Resources

The SDK provides typed methods for all API resources:

ResourceListGet
client.loans.list({ body }).get({ path: { id } })
client.properties.list({ body }).get({ path: { id } })
client.sales.list({ body }).get({ path: { id } })
client.originators.list({ body }).get({ path: { nmlsId } })
client.agents.list({ body }).get({ path: { id } })
client.companies.list({ body }).get({ path: { nmlsId } })
client.offices.list({ body }).get({ path: { id } })
client.branches.list({ body }).get({ path: { nmlsId } })
client.lenders.list({ body }).get({ path: { id } })
client.search.instant({ body })

All .list() methods accept the same filtering, pagination, and sorting options as the REST API.

On this page