The Lookouts API lets you pull your Lens Lookout configuration and the alerts it generates into a system you control — a database, a GIS, a stewardship platform, or a notification pipeline. There are two endpoints: /policies returns the Lookout policies your organization has set up, and /alerts returns the alerts those policies have opened.
Like the note sync APIs, this is a read-only, one-way feed. Lens is the source of truth: dismissing an alert or editing a policy in your own system will not change anything in Lens.
Terminology
- A Lookout policy is the monitoring rule you configure in Lens — a dataset, a threshold or set of categories, spatial and temporal rules, and the set of enrolled properties. In the API a policy is identified by its integer
id, which appears aslookoutPolicyIdeverywhere else. - An alert is a single change notification that a policy opened on one property. In Lens these appear in the Lookout pane and in your notification emails.
Versioning
- The API version is part of the URL, e.g. https://api.upstream.tech/api/v2/lookouts/
- The Lookouts API starts at V2. There is no V1 equivalent.
- We won't remove fields or change types without prior notice, or changing the major version
- We may add new fields without changing the version
- The order of the fields is unspecified and may change
Authentication
Every organization has a Read Only API Token. This token functions as a shared secret. Contact Upstream support to get your API token, or to rotate it.
Unlike the note sync APIs, the Lookouts API takes the token as an apiToken query parameter alongside the other filters:
https://api.upstream.tech/api/v2/lookouts/policies?apiToken=YOUR_READ_ONLY_TOKEN
Because the token travels in the URL, treat request URLs and any logs that capture them as credentials. Requests must be made over HTTPS.
If your organization is not on an Enterprise plan, both endpoints return HTTP status 403.
If you are a parent organization, the token you use determines what you see: a parent organization's token reads that organization's policies and alerts plus those of its child organizations.
Rate limits
Both endpoints are limited to 120 requests / minute. If the request rate is exceeded then HTTP status 429 will be returned. The rate limit is tracked over a sliding window.
Rate limits are tracked per-endpoint, per-organization. If multiple requests use different API tokens for the same organization they'll all count against the same limit.
Shared filters
Both endpoints accept the same four scoping filters. All of them are optional, and they combine — passing several narrows the results to records matching all of them.
| Parameter | Type | What it does |
|---|---|---|
lookoutPolicyId |
integer | On /policies, returns that single policy. On /alerts, returns only the alerts that policy opened. A policy id that doesn't belong to your organization returns HTTP status 404 rather than an empty page. |
projectId |
UUID | A portfolio (called a Project in the APIs). Returns policies set on that portfolio, or alerts on properties in it. |
featureId |
UUID | A property location. On /policies, returns every policy that location is enrolled in. On /alerts, returns the alerts on that location. Properties with multiple locations have one featureId per location — use the note sync APIs' List features for project endpoint to find them. |
updatedAtAfter / updatedAtBefore |
timestamp | Filter on the record's updatedAt time, in YYYY-MM-DDTHH:MMZ format. For example, to represent May 1, 2021 you would use 2021-05-01T00:00Z. If you pass both, updatedAtAfter must be earlier than updatedAtBefore. |
Filtering on updatedAtAfter is the recommended way to keep a copy in sync: store the highest updatedAt you've processed and pass it on the next run.
Unrecognized query parameters are ignored rather than rejected. A misspelled filter will silently return unfiltered results, so check your parameter names against this article if you get more data than you expected.
List Lookout policies
- Rate limit: 120 / min
- URL: https://api.upstream.tech/api/v2/lookouts/policies
- Method: GET
- Query params:
apiToken: your read only API tokenlookoutPolicyId,projectId,featureId,updatedAtAfter,updatedAtBefore: see Shared filtersincludeArchived: set totrueto also return deleted policies. Defaults tofalse.includeEnrolledFeatureIds: set totrueto add anenrolledFeatureIdsarray to each policy. Defaults tofalse.page: for pagination
Results are returned oldest-first, by updatedAt.
Note that the two preset Lookouts — parcel ownership change and parcel area change — are not policies and never appear in the /policies endpoint. Their alerts are returned in the /alerts endpoint. See Alert types.
Pagination
The page query parameter can be used to request different pages of data (starting at 1). The number of results returned in a page is unspecified and may change at Upstream's discretion. To retrieve all policies, continue fetching subsequent pages until hasNextPage is false, or follow the nextPageUrl in each response.
nextPageUrl repeats the filters you sent but not your apiToken, so add the token back when you follow it.
Response format
id: the policy id, used aslookoutPolicyIdon the alerts endpointname,description: the name and description you gave the policy in LensalertType:threshold,category, orvegetation_drop(the preset vegetation drop Lookout)projectId: the UUID of the portfolio the policy is set onsource: the imagery or data source behind the policy's dataset, including resolutionlayer: the display name of the dataset the policy monitorsisArchived: true if the policy has been deleted in LenscreatedAt,updatedAt: ISO formatted timesenrolledFeatureCount: how many property locations are enrolled in the policy. A location enrolled more than once (one enrollment per geometry) is counted once.enrolledFeatureIds: the enrolled property-location UUIDs. Only present whenincludeEnrolledFeatureIds=true.configuration: the rules you set when creating the policyoverlayMethod: how the policy restricts monitoring to an overlay, if you set one. Null when the policy monitors the whole property. The overlay itself is not exposed.minimumAlertingAreaM2: the minimum area of change, in square meters, required to open an alertnumConsecutiveScenes: how many consecutive qualifying scenes are required before an alert opensdateRange: the monitoring season, asstartandendmonth/day pairs that recur each year. Null when the policy runs year-round.direction,value,percentOfProperty: threshold policies only — which side ofvaluetriggers the policy, the threshold value itself, and the percentage of the property that must cross itfromCategories,toCategories: category policies only — the categories a pixel must change from and to
{
"data": [
{
"id": 11,
"name": "Vegetation regrowth — harvest area",
"description": "Watching for regrowth in the 2023 harvest block.",
"alertType": "threshold",
"projectId": "8fbb22e0-2cb7-4fde-8eb1-cef438e24a60",
"source": "ESA Sentinel-2A/B (10m)",
"layer": "Vegetation",
"isArchived": false,
"createdAt": "2020-05-01T00:00:00+00:00",
"updatedAt": "2020-05-01T00:00:00+00:00",
"enrolledFeatureCount": 2,
"configuration": {
"overlayMethod": null,
"minimumAlertingAreaM2": 4000,
"numConsecutiveScenes": 3,
"dateRange": {
"start": { "month": 6, "day": 1 },
"end": { "month": 10, "day": 1 }
},
"direction": "below",
"value": 0.3,
"percentOfProperty": 5
}
}
],
"hasNextPage": false,
"page": 1,
"nextPageUrl": null
}
List alerts
- Rate limit: 120 / min
- URL: https://api.upstream.tech/api/v2/lookouts/alerts
- Method: GET
- Query params:
apiToken: your read only API tokenlookoutPolicyId,projectId,featureId,updatedAtAfter,updatedAtBefore: see Shared filtersalertType: return only alerts of one type. See Alert types.includeDismissed: set totrueto also return alerts that have been dismissed in Lens. Defaults tofalse.sort:asc(the default, oldest first) ordesc(newest first), byupdatedAtafter/before: the pagination token (see below) to continue from. Pass one or the other, not both.
Alerts on archived properties and archived portfolios are not returned.
Alert types
The alertType parameter accepts five values:
threshold— a custom policy watching for a value above or below a thresholdcategory— a custom policy watching for a change between categoriesvegetation_drop— the preset vegetation drop Lookoutparcel_ownership_change— the preset parcel ownership change Lookoutparcel_area_change— the preset parcel area change Lookout
Parcel ownership change and parcel area change alerts are not backed by a Lookout policy. They come from the parcel dataset rather than from a policy you configure, so they have no entry on the /policies endpoint and their lookoutPolicyId is null. alertType is the only way to select them:
https://api.upstream.tech/api/v2/lookouts/alerts?alertType=parcel_ownership_change&apiToken=YOUR_READ_ONLY_TOKEN
For the same reason, a lookoutPolicyId filter will never return them, and a request filtered by any other alertType excludes them.
Pagination
Each alert in the data array has a paginationToken field. This opaque token can be used to retrieve another page of results using the after query parameter (or before, if you are paging with sort=desc). If no token is provided, the earliest results will be returned. Easiest is to follow the nextPageUrl in each response, which already carries the right token and direction, and add your apiToken back to it.
The paginationToken of the last alert processed can be stored to resume synchronization from a known point in the future.
If more results are available, the hasNextPage field will be true. The number of results returned per page is unspecified and may change at Upstream's discretion. To retrieve all alerts, continue fetching subsequent pages until hasNextPage is false.
Response format
The full alert record is returned, not just the fields that have changed. It is the consumer's responsibility to identify the delta between what's stored in their system and the latest changes (or to overwrite what's stored with the latest data from the response).
id: the alert idalertType: the type of the alert (see above). This may be null for a small number of older alerts whose policy is no longer available.lookoutPolicyId: the policy that opened the alert, or null for parcel change alerts and those older alertstext: the alert message, e.g.NDVI below 0.3 detected on 2020-05-27createdAt,updatedAt: ISO formatted times.updatedAtchanges when the alert is dismissed or restored.geometry: a GeoJSON geometry outlining the area of detected changefeatureId: the UUID of the property location the alert is onprojectId: the UUID of the portfolio the property is inorganizationId: the organization the alert belongs to — useful for parent organizations reading across childrenisDismissed: true if the alert has been dismissed in LenslensUrl: a link that opens the alert in LenspaginationToken: see Paginationimages: imagery for the scene that triggered the alert. Each entry includes metadata about the image and a URL to retrieve the image itself. This is an empty array for alerts with no associated imagery, such as parcel change alerts.source: the imagery source and resolutiontype: the dataset shown, e.g.VegetationcapturedAt: when the scene was sensedcopyright: the attribution required when displaying or republishing the imageurl: a signed URL for the image.
{
"data": [
{
"id": 1,
"alertType": "threshold",
"lookoutPolicyId": 11,
"text": "NDVI below 0.3 detected on 2020-05-27",
"createdAt": "2020-05-27T00:01:00+00:00",
"updatedAt": "2020-05-27T00:01:00+00:00",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[-75.19987106323242, 40.05959786095036],
[-75.19785404205322, 40.05959786095036],
[-75.19785404205322, 40.061026662168295],
[-75.19987106323242, 40.061026662168295],
[-75.19987106323242, 40.05959786095036]
]
]
},
"featureId": "6bcee2fb-05db-46a8-a2db-41ed3ab1525a",
"projectId": "8fbb22e0-2cb7-4fde-8eb1-cef438e24a60",
"organizationId": "org-id",
"isDismissed": false,
"lensUrl": "https://app.upstream.tech/org-id/projects/8fbb22e0/map/6bcee2fb#note-1",
"paginationToken": "MXwyMDIwLTA1LTI3IDAwOjAxOjAwKzAwOjAwfDE=",
"images": [
{
"source": "ESA Sentinel-2A/B (10m)",
"type": "Vegetation",
"capturedAt": "2020-01-28T12:23:45+00:00",
"copyright": "Copernicus Sentinel data 2020",
"url": "https://tiler.upstream.tech/api/v1/lookouts/alerts/1/image.png?sensingTime=..."
}
]
}
],
"hasNextPage": false,
"nextPageUrl": null
}
Errors
403: your organization is not on a plan that includes the Lookouts API, or the token doesn't have read access404: thelookoutPolicyId,projectId, orfeatureIdyou filtered on isn't one your token can read422: an invalid query parameter, anupdatedAtAfterthat isn't earlier thanupdatedAtBefore, bothafterandbeforeon the alerts endpoint, or a malformed pagination token. The response body includes anerrorfield describing the problem.429: rate limit exceeded — see Rate limits
Questions?
Reach out to your Upstream contact or email us at lens@upstream.tech and we'll be happy to help you get set up.