Portfolio Monitoring: API Quickstart
This guide explains how to use the Baselayer Portfolio Monitoring API to:
- Search for and verify a business
- Add that business to a monitored portfolio
- Retrieve ongoing updates and changes for that business
- Drill into field-level changes over time
This guide is designed to be used alongside the provided Postman collection (access the file here).
For background on portfolios, groups, policies, and how to design monitoring, see Portfolio Monitoring: Basics.
Overview
The Portfolio Monitoring API lets you:
- Search for a business by name and address
- Create a portfolio item from that search result
- Poll portfolio updates to see what has changed (registrations, officers, scores, watchlists, etc.)
- Drill into changes for a specific portfolio item to see field-level diffs
High-Level Flow
-
Search for a business
POST /searches(synchronous search) -
Add the business to your portfolio
POST /portfolio/items -
Fetch portfolio updates
GET /portfolio/updates -
Paginate through updates
Use the
X-Next-Cursorresponse header -
Inspect changes for a specific item (optional)
GET /portfolio/items/{item_id}/changes
Base URL & Authentication
Base URL
Use the appropriate environment base URL in your integration:
- Production:
https://api.baselayer.com - Staging (examples in this doc):
https://api.staging.baselayer.com
In the examples below, we refer to this as:
{{baseUrl}}(e.g., {{baseUrl}} = https://api.staging.baselayer.com)
Authentication
All requests are authenticated using an API key via the X-API-Key header:
X-API-Key: {{apiKey}}In Postman, this is configured at the collection level using the API Key auth type with:
- Key:
X-API-Key - Value:
{{apiKey}}
You can then define {{apiKey}} as an environment variable.
Step 1 – Business Search
Use the Business Search endpoint to look up and verify a business by name and address.
Endpoint
POST /searches
Content-Type: application/jsonRequest Body Example
{
"name": "22645 anza avenue statutory trust",
"address": "1718 capitol avenue cheyenne wy 82001"
}Sample Response (Truncated)
{
"id": "4dc4fd78-b7de-4ee8-ade0-dbd455e48ca6",
"state": "COMPLETED",
"name": "22645 anza avenue statutory trust",
"address": "1718 capitol avenue cheyenne wy 82001",
"search_address": {
"id": "587c35d9-7ec4-48bb-a421-7b20c4db005c",
"street": "1716 Capitol Ave Ste 100",
"city": "Cheyenne",
"state": "WY",
"zip": "82001",
"latitude": 41.13403,
"longitude": -104.81626,
"rdi": "Commercial",
"deliverable": true,
"cmra": false,
"url": "https://api.staging.baselayer.com/addresses/587c35d9-7ec4-48bb-a421-7b20c4db005c",
"delivery_type": "STREET"
},
"business_name_match": "EXACT",
"business_address_match": "EXACT",
"scores": [
{
"type": "kyb",
"score": 100.0,
"rating": "A"
},
{
"type": "risk",
"score": 100.0,
"rating": "A"
}
],
"business": {
"id": "428ee4cc-39c0-4f8f-981a-95dbe5f8bbe3",
"name": "22645 Anza Avenue Statutory Trust",
"structure": "TRUST",
"addresses": [
{
"id": "96ab5659-0a69-415e-a5f7-76e992ae7bd0",
"street": "1718 Capitol Ave",
"city": "Cheyenne",
"state": "WY",
"zip": "82001"
},
{
"id": "587c35d9-7ec4-48bb-a421-7b20c4db005c",
"street": "1716 Capitol Ave Ste 100",
"city": "Cheyenne",
"state": "WY",
"zip": "82001"
}
],
"incorporation_state": "WY",
"incorporation_date": "2021-01-01",
"months_in_business": 58,
"registrations": [/* ... */],
"business_officers": [/* ... */],
"watchlist_hits": [
{
"code": "IEO",
"name": "IRS Exempt Organizations List",
"count": 0,
"details": []
}
],
"url": "https://api.staging.baselayer.com/businesses/428ee4cc-39c0-4f8f-981a-95dbe5f8bbe3",
"console_url": "https://console.staging.baselayer.com/business/428ee4cc-39c0-4f8f-981a-95dbe5f8bbe3",
"address": "1716 Capitol Ave Ste 100, Cheyenne, WY 82001"
},
"url": "https://api.staging.baselayer.com/searches/4dc4fd78-b7de-4ee8-ade0-dbd455e48ca6",
"status_url": "https://api.staging.baselayer.com/searches/4dc4fd78-b7de-4ee8-ade0-dbd455e48ca6/status",
"business_url": "https://api.staging.baselayer.com/businesses/428ee4cc-39c0-4f8f-981a-95dbe5f8bbe3",
"console_url": "https://console.staging.baselayer.com/business/428ee4cc-39c0-4f8f-981a-95dbe5f8bbe3?searchId=4dc4fd78-b7de-4ee8-ade0-dbd455e48ca6"
}Key Fields to Capture
From this response you’ll typically store:
id– the search id (e.g.4dc4fd78-b7de-4ee8-ade0-dbd455e48ca6)business.id– the business id (e.g.428ee4cc-39c0-4f8f-981a-95dbe5f8bbe3)scores– KYB and risk scores at time of searchbusinessdetails – structure, registrations, officers, addresses, watchlists, etc.
The business search must be completed and must have matched to a business profile to be able to add the search as a portfolio Item.
You’ll use the search id in the next step to create a portfolio item.
Step 2 – Add the Business to Your Portfolio
Once you’ve verified the search result, add it to the portfolio for ongoing monitoring.
Endpoint
POST /portfolio/items
Content-Type: application/jsonRequest Body Example
{
"business_search_id": "4dc4fd78-b7de-4ee8-ade0-dbd455e48ca6"
}Note:
business_search_idshould be theidfield from the search response.
Sample Response
{
"id": "825667a6-2fe0-432d-ae59-edddab3ce068",
"business_id": "428ee4cc-39c0-4f8f-981a-95dbe5f8bbe3",
"business": {
"id": "428ee4cc-39c0-4f8f-981a-95dbe5f8bbe3",
"name": "22645 Anza Avenue Statutory Trust",
"address": "1716 Capitol Ave Cheyenne WY 82001",
"incorporation_date": "2021-01-01",
"structure": "TRUST",
"ein": null,
"incorporation_state": "WY",
"phone_number": null,
"email": null,
"website": null,
"url": "https://api.staging.baselayer.com/businesses/428ee4cc-39c0-4f8f-981a-95dbe5f8bbe3",
"console_url": "https://console.staging.baselayer.com/business/428ee4cc-39c0-4f8f-981a-95dbe5f8bbe3"
},
"group_id": null,
"name": "22645 anza avenue statutory trust",
"address": "1718 capitol avenue cheyenne wy 82001",
"business_name_match": "EXACT",
"business_address_match": "EXACT",
"verified": true,
"scores": [
{
"type": "kyb",
"score": 100,
"rating": "A"
},
{
"type": "risk",
"score": 100,
"rating": "A"
}
],
"created_at": "2025-11-26T20:27:41.824138Z",
"last_monitored_at": null
}Key Fields to Capture
id– portfolio item id (e.g.825667a6-2fe0-432d-ae59-edddab3ce068)business_id– underlying Baselayer business idscores– KYB & risk scores at the time the business was added to the portfolio
You’ll use the portfolio id later to request detailed changes for this item.
Step 3 – Fetch Portfolio Updates
Portfolio updates capture changes over time for items in your portfolio. These include:
- Registration standing changes (e.g., Good → Suspended → Active)
- KYB and risk score changes
- Address and officer changes
- Watchlist changes (OFAC, PEP, etc.)
Endpoint
GET /portfolio/updatesOptional query parameters:
limit– maximum number of updates to return per pagecursor– pagination cursor (see the pagination section below)
Sample Response
[
{
"item": {
"id": "825667a6-2fe0-432d-ae59-edddab3ce068",
"name": "22645 anza avenue statutory trust",
"business_id": "428ee4cc-39c0-4f8f-981a-95dbe5f8bbe3",
"group_id": null,
"assignee": null,
"scores": [
{
"type": "kyb",
"score": 100.0,
"rating": "A"
},
{
"type": "risk",
"score": 100.0,
"rating": "A"
}
],
"created_at": "2025-11-26T20:27:41.824138Z",
"item_url": "https://api.staging.baselayer.com/portfolio/items/825667a6-2fe0-432d-ae59-edddab3ce068",
"group_url": null,
"console_url": "https://console.staging.baselayer.com/portfolio-monitoring/items/825667a6-2fe0-432d-ae59-edddab3ce068"
},
"from_snapshot_id": "b7d967d7-dbff-405d-8dc2-6a14d1d97c72",
"to_snapshot_id": "4c2cd1ff-f92e-496e-a926-9f58b5f42478",
"change_count": 7,
"notification_count": 7,
"notification_summaries": [
{ "attribute": "new_registrations", "count": 0 },
{ "attribute": "registration_standing", "count": 1 },
{ "attribute": "addresses", "count": 1 },
{ "attribute": "officers", "count": 1 },
{ "attribute": "alternative_names", "count": 0 },
{ "attribute": "kyb_score", "count": 1 },
{ "attribute": "risk_score", "count": 1 },
{ "attribute": "identity_network", "count": 0 },
{ "attribute": "pep", "count": 1 },
{ "attribute": "ofac", "count": 1 },
{ "attribute": "liens", "count": 0 },
{ "attribute": "litigations", "count": 0 },
{ "attribute": "bankruptcies", "count": 0 },
{ "attribute": "website_analysis", "count": 0 }
],
"created_at": "2025-11-26T20:27:41.980342Z",
"item_url": "https://api.staging.baselayer.com/portfolio/items/825667a6-2fe0-432d-ae59-edddab3ce068",
"from_snapshot_url": "https://api.staging.baselayer.com/portfolio/items/825667a6-2fe0-432d-ae59-edddab3ce068/snapshots/b7d967d7-dbff-405d-8dc2-6a14d1d97c72",
"to_snapshot_url": "https://api.staging.baselayer.com/portfolio/items/825667a6-2fe0-432d-ae59-edddab3ce068/snapshots/4c2cd1ff-f92e-496e-a926-9f58b5f42478",
"diff_url": "https://api.staging.baselayer.com/portfolio/items/825667a6-2fe0-432d-ae59-edddab3ce068/diff?from_snapshot_id=b7d967d7-dbff-405d-8dc2-6a14d1d97c72&to_snapshot_id=4c2cd1ff-f92e-496e-a926-9f58b5f42478",
"notifications_url": "https://api.staging.baselayer.com/portfolio/items/825667a6-2fe0-432d-ae59-edddab3ce068/diff?from_snapshot_id=b7d967d7-dbff-405d-8dc2-6a14d1d97c72&to_snapshot_id=4c2cd1ff-f92e-496e-a926-9f58b5f42478&format=notifications",
"notifications": [
{
"message": {
"text": "State Registration - Wyoming Standing changed from Suspended to Active. (Domestic)"
},
"notifiable_attribute": "registration_standing"
},
{
"message": {
"text": "KYB Score increased from C to B."
},
"notifiable_attribute": "kyb_score"
},
{
"message": {
"text": "Risk Score decreased from B to A."
},
"notifiable_attribute": "risk_score"
},
{
"message": {
"text": "Address removed: 123 Sandbox Lane, Test City, CA 90210."
},
"notifiable_attribute": "addresses"
},
{
"message": {
"text": "Officer removed: Jane Sandbox Smith (Chief Sandbox Officer)."
},
"notifiable_attribute": "officers"
},
{
"message": {
"text": "OFAC watchlist hit removed: 1 hit."
},
"notifiable_attribute": "ofac"
},
{
"message": {
"text": "PEP watchlist hit removed: 1 hit."
},
"notifiable_attribute": "pep"
}
]
},
{
"item": {
"id": "825667a6-2fe0-432d-ae59-edddab3ce068",
"name": "22645 anza avenue statutory trust",
"business_id": "428ee4cc-39c0-4f8f-981a-95dbe5f8bbe3",
"group_id": null,
"assignee": null,
"scores": [
{
"type": "kyb",
"score": 100.0,
"rating": "A"
},
{
"type": "risk",
"score": 100.0,
"rating": "A"
}
],
"created_at": "2025-11-26T20:27:41.824138Z",
"item_url": "https://api.staging.baselayer.com/portfolio/items/825667a6-2fe0-432d-ae59-edddab3ce068",
"group_url": null,
"console_url": "https://console.staging.baselayer.com/portfolio-monitoring/items/825667a6-2fe0-432d-ae59-edddab3ce068"
},
"from_snapshot_id": "cfbd361c-98b4-411d-850c-4a7bdcc311b9",
"to_snapshot_id": "b7d967d7-dbff-405d-8dc2-6a14d1d97c72",
"change_count": 7,
"notification_count": 7,
"notification_summaries": [
{ "attribute": "new_registrations", "count": 0 },
{ "attribute": "registration_standing", "count": 1 },
{ "attribute": "addresses", "count": 1 },
{ "attribute": "officers", "count": 1 },
{ "attribute": "alternative_names", "count": 0 },
{ "attribute": "kyb_score", "count": 1 },
{ "attribute": "risk_score", "count": 1 },
{ "attribute": "identity_network", "count": 0 },
{ "attribute": "pep", "count": 1 },
{ "attribute": "ofac", "count": 1 },
{ "attribute": "liens", "count": 0 },
{ "attribute": "litigations", "count": 0 },
{ "attribute": "bankruptcies", "count": 0 },
{ "attribute": "website_analysis", "count": 0 }
],
"created_at": "2025-11-19T20:27:41.980342Z",
"item_url": "https://api.staging.baselayer.com/portfolio/items/825667a6-2fe0-432d-ae59-edddab3ce068",
"from_snapshot_url": "https://api.staging.baselayer.com/portfolio/items/825667a6-2fe0-432d-ae59-edddab3ce068/snapshots/cfbd361c-98b4-411d-850c-4a7bdcc311b9",
"to_snapshot_url": "https://api.staging.baselayer.com/portfolio/items/825667a6-2fe0-432d-ae59-edddab3ce068/snapshots/b7d967d7-dbff-405d-8dc2-6a14d1d97c72",
"diff_url": "https://api.staging.baselayer.com/portfolio/items/825667a6-2fe0-432d-ae59-edddab3ce068/diff?from_snapshot_id=cfbd361c-98b4-411d-850c-4a7bdcc311b9&to_snapshot_id=b7d967d7-dbff-405d-8dc2-6a14d1d97c72",
"notifications_url": "https://api.staging.baselayer.com/portfolio/items/825667a6-2fe0-432d-ae59-edddab3ce068/diff?from_snapshot_id=cfbd361c-98b4-411d-850c-4a7bdcc311b9&to_snapshot_id=b7d967d7-dbff-405d-8dc2-6a14d1d97c72&format=notifications",
"notifications": [
{
"message": {
"text": "State Registration - Wyoming Standing changed from Good Standing to Suspended. (Domestic)"
},
"notifiable_attribute": "registration_standing"
},
{
"message": {
"text": "KYB Score decreased from A to C."
},
"notifiable_attribute": "kyb_score"
},
{
"message": {
"text": "Risk Score increased from A to B."
},
"notifiable_attribute": "risk_score"
},
{
"message": {
"text": "Address added: 123 Sandbox Lane, Test City, CA 90210."
},
"notifiable_attribute": "addresses"
},
{
"message": {
"text": "Officer added: Jane Sandbox Smith (Chief Sandbox Officer)."
},
"notifiable_attribute": "officers"
},
{
"message": {
"text": "OFAC watchlist hit added: 1 hit."
},
"notifiable_attribute": "ofac"
},
{
"message": {
"text": "PEP watchlist hit added: 1 hit."
},
"notifiable_attribute": "pep"
}
]
}
]Interpreting an Update
Each array element represents changes between two snapshots of a portfolio item:
item– basic portfolio item metadatafrom_snapshot_id/to_snapshot_id– snapshot identifiers for diffingnotification_summaries– counts of changes per attribute categorynotifications– human-readable change messages (good for dashboards, emails, etc.)diff_url/notifications_url– API URLs to fetch structured diffs or notifications for this change window
You can use notification_summaries to quickly understand what kind of changes occurred, then drill into notifications or /portfolio/items/{item_id}/changes for details.
Step 4 – Pagination with X-Next-Cursor
X-Next-CursorThe /portfolio/updates endpoint uses cursor-based pagination.
When there are more updates available, the response headers include something like:
X-Next-Cursor: eyJjcmVhdGVkX2F0IjoiMjAyNC0wMS0xNVQxMDozMDowMFoiLCJpZCI6IjEyMzQ1In0=You can pass that value back to the endpoint as a cursor query parameter, for example:
GET /portfolio/updates?limit=50&cursor=eyJjcmVhdGVkX2F0IjoiMjAyNC0wMS0xNVQxMDozMDowMFoiLCJpZCI6IjEyMzQ1In0=Recommended Pattern
- Call
GET /portfolio/updates?limit=50 - Process all updates in the response
- If the
X-Next-Cursorheader is present, call the endpoint again withcursor=<value> - Repeat until no
X-Next-Cursorheader is returned
This pattern works well in a scheduled job (for example, every few minutes) to ingest new portfolio changes.
Step 5 – Inspect Field-Level Changes for a Portfolio Item
If you need structured, field-level information about what changed for a particular item, use the item changes endpoint.
Endpoint
GET /portfolio/items/{item_id}/changesWhere {item_id} is the portfolio item id (for example, 825667a6-2fe0-432d-ae59-edddab3ce068).
Sample Response
[
{
"path": "/business/corporate_registrations/0/standing",
"operation": "replace",
"old_value": "Suspended",
"new_value": "Active",
"changed_at": "2025-11-26T20:27:41.980342Z"
},
{
"path": "/scores/0",
"operation": "replace",
"old_value": {
"type": "kyb",
"score": 65.0,
"rating": "C"
},
"new_value": {
"type": "kyb",
"score": 75.0,
"rating": "B"
},
"changed_at": "2025-11-26T20:27:41.980342Z"
},
{
"path": "/scores/1",
"operation": "replace",
"old_value": {
"type": "risk",
"score": 45.0,
"rating": "B"
},
"new_value": {
"type": "risk",
"score": 30.0,
"rating": "A"
},
"changed_at": "2025-11-26T20:27:41.980342Z"
},
{
"path": "/business/addresses/0",
"operation": "remove",
"old_value": {
"id": "00000000-0000-0000-0000-000000000002",
"street": "123 Sandbox Lane",
"city": "Test City",
"state": "CA",
"zip": "90210",
"latitude": 34.0901,
"longitude": -118.4065,
"rdi": null,
"deliverable": null,
"cmra": false,
"url": null,
"delivery_type": null,
"sources": []
},
"new_value": null,
"changed_at": "2025-11-26T20:27:41.980342Z"
},
{
"path": "/business/watchlists/0",
"operation": "remove",
"old_value": {
"code": "OFAC",
"name": "Department of Treasury, Office of Foreign Assets Control",
"count": 1,
"details": [
{
"name": "Sandbox OFAC Match",
"address": "123 Test Street, Test City, CA 90210",
"match_score": 0.85
}
]
},
"new_value": null,
"changed_at": "2025-11-26T20:27:41.980342Z"
},
{
"path": "/business/watchlists/1",
"operation": "remove",
"old_value": {
"code": "PEP",
"name": "Politically Exposed Persons",
"count": 1,
"details": [
{
"name": "Sandbox PEP Match",
"country": "US",
"position": "Test Official",
"match_score": 0.78
}
]
},
"new_value": null,
"changed_at": "2025-11-26T20:27:41.980342Z"
},
{
"path": "/business/business_officers/0",
"operation": "remove",
"old_value": {
"name": "Jane Sandbox Smith",
"titles": [
"Chief Sandbox Officer"
],
"states": [
"CA"
]
},
"new_value": null,
"changed_at": "2025-11-26T20:27:41.980342Z"
},
{
"path": "/business/corporate_registrations/0/standing",
"operation": "replace",
"old_value": "Good Standing",
"new_value": "Suspended",
"changed_at": "2025-11-19T20:27:41.980342Z"
},
{
"path": "/scores/0",
"operation": "replace",
"old_value": {
"type": "kyb",
"score": 85.0,
"rating": "A"
},
"new_value": {
"type": "kyb",
"score": 65.0,
"rating": "C"
},
"changed_at": "2025-11-19T20:27:41.980342Z"
},
{
"path": "/scores/1",
"operation": "replace",
"old_value": {
"type": "risk",
"score": 20.0,
"rating": "A"
},
"new_value": {
"type": "risk",
"score": 45.0,
"rating": "B"
},
"changed_at": "2025-11-19T20:27:41.980342Z"
},
{
"path": "/business/addresses/0",
"operation": "add",
"old_value": null,
"new_value": {
"id": "00000000-0000-0000-0000-000000000002",
"street": "123 Sandbox Lane",
"city": "Test City",
"state": "CA",
"zip": "90210",
"latitude": 34.0901,
"longitude": -118.4065,
"rdi": null,
"deliverable": null,
"cmra": false,
"url": null,
"delivery_type": null,
"sources": []
},
"changed_at": "2025-11-19T20:27:41.980342Z"
},
{
"path": "/business/watchlists/0",
"operation": "add",
"old_value": null,
"new_value": {
"code": "OFAC",
"name": "Department of Treasury, Office of Foreign Assets Control",
"count": 1,
"details": [
{
"name": "Sandbox OFAC Match",
"address": "123 Test Street, Test City, CA 90210",
"match_score": 0.85
}
]
},
"changed_at": "2025-11-19T20:27:41.980342Z"
},
{
"path": "/business/watchlists/1",
"operation": "add",
"old_value": null,
"new_value": {
"code": "PEP",
"name": "Politically Exposed Persons",
"count": 1,
"details": [
{
"name": "Sandbox PEP Match",
"country": "US",
"position": "Test Official",
"match_score": 0.78
}
]
},
"changed_at": "2025-11-19T20:27:41.980342Z"
},
{
"path": "/business/business_officers/0",
"operation": "add",
"old_value": null,
"new_value": {
"name": "Jane Sandbox Smith",
"titles": [
"Chief Sandbox Officer"
],
"states": [
"CA"
]
},
"changed_at": "2025-11-19T20:27:41.980342Z"
}
]Interpreting the Change Objects
Each object represents a single change:
path– JSON path within the portfolio item document that changedoperation–"add","remove", or"replace"old_value– value before the change (ornullforadd)new_value– value after the change (ornullforremove)changed_at– timestamp of the change
These are ideal for:
- Internal audit logs
- Driving your own notification or workflow system
- Building detailed “change history” or “activity log” UIs
End-to-End User Flow Summary
A typical integration to monitor a business with Baselayer looks like this:
-
Search and verify
- Call
POST /searcheswith the business name and address. - Review
business,scores, and match quality fields.
- Call
-
Create a portfolio item
- Call
POST /portfolio/itemswithbusiness_search_idfrom step 1. - Store the returned portfolio
id.
- Call
-
Poll for updates
- Periodically call
GET /portfolio/updates?limit=50. - Use
X-Next-Cursorto paginate through all updates. - Use
notification_summariesandnotificationsto decide when to alert or trigger workflows.
- Periodically call
-
Drill into details as needed
- Call
GET /portfolio/items/{item_id}/changesfor item-level diffs. - Optionally use
diff_urlandnotifications_urlfrom each update for more specialized views.
- Call
With this flow implemented, your system will have continuous visibility into changes to the businesses you monitor (scores, registrations, officers, addresses, and watchlists) via Baselayer’s Portfolio Monitoring API.
Updated about 2 months ago
