API Documentation
The Listings API is compliant to the RESO Web API standard for transfer of real estate data. The data follows the RESO Data Dictionary standard for field naming, grouping and data type definition.
Data retrieval largely follows OData protocol with the addition of custom querying options to enhance aggregation queries.
Authentication
Access to the API utilizes OAuth2.
Client Credentials (ID and secret) are provided for each user of the API, allowing for retrieval of bearer access token with preset expiry (default 3600 seconds).
We must encode the combination of Client ID and Client Secret Key separated by “:” in Base 64 format like this:
Base64Encode(5pq9999coididi613e222o1nnpp: fhkoq33a69d8191j1tercv35037clb9e5a7d215e64e4e) = 85e1b0e7539a4a96b00ee02b335aa6418c580917a6b4667f6f7a6fe2149536041569924dfbe4a7df33f==
Can use online service Base64Encode for the encoding.
The end point for the token must include two parameters:
- "grant_type" = "client_credentials"
- "client_id" = "5pq9999coididi613e222o1nnpp"
Example request to retrieve access token:
curl -X POST -H "Content-Type: application/x-www-form-urlencoded" \
-H "Authorization: Basic 85e1b0e7539a4a96b00ee02b335aa6418c580917a6b4667f6f7a6fe2149536041569924dfbe4a7df33f==" \
-H "Host: authenticate.constellation1apis.com" \
"https://authenticate.constellation1apis.com/oauth2/token?grant_type=client_credentials&client_id=5pq9999coididi613e222o1nnpp"
Authentication response:
{
"access_token": "**********************************",
"expires_in": 3600,
"token_type": "Bearer"
}
Usage
Once the access token is retrieved, it is needed in each call to the Constellation1 API under the Authorization HTTP header:
curl -X GET -i -H "Host: listings.constellation1apis.com" \
-H "Authorization: Bearer **********************************" \
"https://listings.constellation1apis.com/odata/Property?$top=5&$select=ListingKey,StreetNumberNumeric"
Recommendation: It is recommended to include 'Accept-Encoding' header with value 'gzip, deflate, br'. This will compress the response into a zip/brotli format. This should improve the latency in transit by compressing the size. Client will have to decompress the response before processing it:
Header | Value |
---|---|
Accept-Encoding | gzip, deflate, br |
Metadata
The Listings API has an endpoint to retrieve metadata:
https://listings.constellation1apis.com/odata/$metadata
This endpoint allows caller to know available fields and data types for each entity.
<?xml version="1.0" encoding="utf-8" ?>
<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">
<edmx:DataServices>
<Schema Namespace="Cirrus.OData.Domain.Models" xmlns="http://docs.oasis-open.org/odata/ns/edm">
<EntityType Name="Property">
<Property Name="AccessibilityFeatures" Type="Collection(Edm.String)" />
<Property Name="Appliances" Type="Collection(Edm.String)" />
<Property Name="ArchitecturalStyle" Type="Collection(Edm.String)" />
...
</EntityType>
<EntityType Name="OpenHouse" />
<EntityType Name="Member" />
<EntityType Name="Office" />
<EntityType Name="Media" />
<EntityType Name="Dom" />
</Schema>
<Schema Namespace="org.reso.metadata.enums" xmlns="http://docs.oasis-open.org/odata/ns/edm">
<EnumType Name="ArchitecturalStyle" UnderlyingType="Edm.Int64" />
<EnumType Name="Appliances" />
...
</Schema>
</edmx:DataServices>
</edmx:Edmx>
Entities
The Listings API supports several entity types, primarily Property which represents a real estate listing. Other entity types such as Media represents supplementary data to a listing such as photos.
Entity | Description | URL |
---|---|---|
Property | Real Estate Listing | https://listings.constellation1apis.com/odata/Property |
Member | MLS Agent | https://listings.constellation1apis.com/odata/Member |
Office | MLS Office | https://listings.constellation1apis.com/odata/Office |
Media | Photos, Virtual Tours, etc. | https://listings.constellation1apis.com/odata/Media |
OpenHouse | Open House Events | https://listings.constellation1apis.com/odata/OpenHouse |
Dom | Days on Market | https://listings.constellation1apis.com/odata/Dom |
PropertyUnitTypes | Property Units | https://listings.constellation1apis.com/odata/PropertyUnitTypes |
PropertyRooms | Property Rooms | https://listings.constellation1apis.com/odata/PropertyRooms |
RawMlsProperty | Raw Mls Data Fields | https://listings.constellation1apis.com/odata/RawMlsProperty |
Basic Requests
Following OData protocol, the following examples show how combining options and filters can retrieve a desired subset of real estate data results.
GET /odata/property?$select=...&$filter=...&$top=...&$orderby=...&$ignorenulls=...
API response structure
{
"@@odata.context": "...",
"@@odata.count": 0,
"@@odata.totalCount": 0,
"value": [],
"group": [],
"@@odata.nextLink": "...",
"debug": { ... },
}
Field | Description |
---|---|
@@odata.context | annotation of the request |
@@odata.count | number of records returned in response, default is 10 |
@@odata.totalCount | total number of records found in result set |
value | result set from query |
group | used for aggregation results |
@@odata.nextLink | used for server side, allows user to cycle through entire result set |
debug | hidden by default, used for troubleshooting and insight into underlying search criteria |
Time Range Queries
Select
By default, the entire set of fields are returned, however, we can whitelist specific fields in the response using $select. Whitelist fields are specified in a comma separated list.
Example request:
GET /odata/property?$select=ListingId,StandardStatus
Example response:
{
"@@odata.context": "https://listings.constellation1apis.com/$metadata#Property",
"@@odata.count": 10,
"@@odata.totalCount": 100,
"value": [
{
"ListingId": "1",
"StandardStatus": "Active"
},
{
"ListingId": "2",
"StandardStatus": "Active"
}
...
]
}
Top
By default, the first 10 results are returned in any API request, however we can alter the number of results by using the $top option followed by a non-negative integer value.
Example request:
GET /odata/Property?$top=1
Recommendation: It is recommended to not exceed $top=1000 with $ignorenulls=true flag. Exceeding this limit will cause slowness of response payloads
Skip
Note: It is ideal and more performant to use the SkipToken approach to paging through result sets
Often in combination with $top, the $skip option allows for client side paging, also using a non-negative integer we can cycling through the entire result set.
Example request:
GET /odata/Property?$top=5&skip=2
Ignore Nulls (preferred)
By default, the response payload will include all fields defined in the metadata where null is returned when there is no value. The $ignorenulls boolean flag will omit fields which have no values thus reducing payload size
Example request:
GET /odata/Property?$ignorenulls=true
Ignore Case
By default, searches are case sensitive. The $ignorecase boolean flag will do case-insensitve searches for supported text fields.
Example request:
GET /odata/Property?$filter=BuildingName eq 'The Great House'&$ignorecase=true
All supported fields are mentioned below:
Property | ||||
---|---|---|---|---|
BuildingName | BuyerAgentEmail | BuyerAgentFirstName | BuyerAgentFullName | BuyerAgentLastName |
BuyerAgentMiddleName | BuyerAgentMlsId | BuyerOfficeEmail | BuyerOfficeMlsId | BuyerOfficeName |
CityRegion | CoBuyerAgentEmail | CoBuyerAgentFirstName | CoBuyerAgentFullName | CoBuyerAgentLastName |
CoBuyerAgentMiddleName | CoBuyerAgentMlsId | CoBuyerOfficeEmail | CoBuyerOfficeMlsId | CoBuyerOfficeName |
CoListAgentEmail | CoListAgentFirstName | CoListAgentFullName | CoListAgentLastName | CoListAgentMiddleName |
CoListAgentMlsId | CoListOfficeEmail | CoListOfficeMlsId | CoListOfficeName | CountyOrParish |
ElementarySchool | ElementarySchoolDistrict | HighSchool | HighSchoolDistrict | ListAgentEmail |
ListAgentFirstName | ListAgentFullName | ListAgentLastName | ListAgentMlsId | ListingId |
ListOfficeEmail | ListOfficeMlsId | ListOfficeName | MiddleOrJuniorSchoolDistrict | SchoolDistrict |
StateOrProvince | StreetDirPrefix | StreetName | StreetNumber | StreetNumberNumeric |
StreetSuffix | SubdivisionName | UnitNumber | UnparsedAddress | |
Office | ||||
MainOfficeMlsId | OfficeCity | OfficeEmail | OfficeMlsId | OfficeName |
Member | ||||
MemberEmail | MemberFirstName | MemberFullName | MemberLastName | MemberMiddleName |
MemberMlsId |
Filter
Most common option is $filter, typically at least one filter is used when retrieving data, often used are comparison operators to filter results by an MLS (Data Source) via the OriginatingSystemName field.
The following is a list of supported operators and expressions. In future additional OData expressions could be added to the API.
Comparison Operators
Note: single quotation is required for string values
Operator | Description | Example |
---|---|---|
eq | Equal | GET /odata/Property?$filter=OriginatingSystemName eq 'CRMLS' |
ne | Not Equal | GET /odata/Property?$filter=StandardStatus ne 'Active' |
gt | Greater Than | GET /odata/Property?$filter=ListPrice gt 100000 |
ge | Greater Than or Equal | GET /odata/Property?$filter=ListPrice ge 100000 |
lt | Less Than | GET /odata/Property?$filter=ListPrice lt 200000 |
le | Less Than or Equal | GET /odata/Property?$filter=ListPrice le 200000 |
has | Has enumerable | GET /odata/Property?$filter=Appliances has 'Freezer' |
in | Is a member of | GET /odata/Property?$filter=StandardStatus in ('Active','Sold') |
The any expression is required for fields which are collections as defined in the metadata endpoint where the field is defined as Type="Collection(Edm.String)" (e.g. Appliances).
Boolean Operators
Note: boolean operator is expressed in lower cased
Often used to chain multiple comparison expressions, the boolean operators and and or can precise subset of real estate listings
Operator | Description | Example |
---|---|---|
and | Logical AND | GET /odata/Property?$filter=OriginatingSystemName eq 'CRMLS' and StandardStatus eq 'Active' |
or | Logical OR | GET /odata/Property?$filter=OriginatingSystemName eq 'VirginIslands' or OriginatingSystemName eq 'WesternKY' |
Using Standard Lookup Values
Lookups (as defined in Lookups-RESO Data Dictionary 1.7-RESO ) are enumerations where normally their values do not contain special characters or spaces. In situations where they do, they can be filtered using the standard lookup value defined in the RESO data dictionary along with the prefix 'org.reso.metadata.enums'.
Example requests:
GET /odata/Property?$filter=org.reso.metadata.enums.PropertyType eq 'Commercial Sale'
GET /odata/Property?$filter=org.reso.metadata.enums.StandardStatus eq 'Active Under Contract'
GET /odata/Property?$filter=org.reso.metadata.enums.PropertySubType eq 'Single Family Residence'
Functions
startswith()
In support of partial and autocomplete queries, the startswith() provides the ability to return results of partial values, such as beginning of a street name or postal/zip code.
Example requests:
GET /odata/Property?$filter=startswith(PostalCode, '902')
GET /odata/Property?$filter=startswith(PostalCode, '9021')
GET /odata/Property?$filter=startswith(PostalCode, '90210')
contains()
The contains() function complements the startswith() function as it allows for wildcard searches with the use of the asterisk symbol *, this can be expressed before, after, or within a search term
Example requests:
GET /odata/Property?$filter=contains(SubdivisionName, 'Park*')
GET /odata/Property?$filter=contains(SubdivisionName, '*Arlington')
GET /odata/Property?$filter=contains(SubdivisionName, 'P*rk')
GET /odata/Property?$filter=contains(SubdivisionName, '*Arlington Park*')
Geospatial Search
Radius
A radius search returns listings which are located within distance from a fixed point on a map. The function used for radius search “geo.distance” accepts two parameters representing the field (“Location”) and a fixed point (latitude/longitude), followed by a less than operator with a distance value represented by meters.
Example request:
GET /odata/Property?$filter= geo.distance(Location, geography'POINT(-82.5154 40.7584)') lt 1000.0
Polygon
A Polygon is a series of coordinates (longitude/latitude pairs) which can represent basic shapes, typically a Polygon’s first and last coordinates match to form a closed shape. Our API supports the “geo.intersects” canonical function which accepts two parameters, firstly the field (“Location”) representing the latitude/longitude of each listing and second the Polygon shape where listings are located within.
Example requests:
GET /odata/Property?$filter=geo.intersects(Location, geography'POLYGON((-82.5294685 40.7700118, -82.5081825 40.7698818, -82.5064659 40.7493377, -82.5272369 40.7489476, -82.5294685 40.7700118))')
Expand
In OData, the $expand allows for retrieval of supplementary entity data where there is an association to the primary entity. Typically $expand would be used where Property is the primary EntityType. Expand can retrieve multiple sub-entities using a comma separated list.
Example requests:
GET /odata/Property?$expand=Media
GET /odata/Property?$expand=Media,OpenHouse
Recommendation: It is recommended to not exceed $top=500 with $expand as $expand increases the payload size and query time, potentially resulting in a degradation of service.
Select in Expand
The $select option within $expand allows for the retrieval of specific fields from the expanded resources. This can help in reducing the payload size by selecting only the necessary fields.
Example request:
GET /odata/Property?$expand=Office($select=OfficeType)
Paging (SkipToken)
When making a request to the API that yields a larger amount of results than what is presentable in the response payload, the response payload will include the node "@@odata.nextLink" with a hyperlink to the next set of results. This "@@odata.nextLink" node will reappear until all results has been retrieved.
Example response:
{
"@@odata.context": "https://listings.constellation1apis.com/$metadata#Property",
"@@odata.count": 10,
"@@odata.totalCount": 2295,
"value": [ ... ],
"group": [],
"@@odata.nextLink": "https://listings.constellation1apis.com/property/skiptoken/FGluY2x1ZGVfY29udGV4dF91dWlkDnF1ZXJ5VGhlbkZldGNoBRYxd3h4RWFXRlQwYWtDbGZjdkd0aTNBAA",
}
Ordering
To sort results, the $orderby option can be used, providing the desired sort field and direction, if direction is not provided by default it is assumed the sort order is ascending. Multiple order by expressions can be provided by a comma separated list.
Example requests:
GET /odata/Property?$orderby=ModificationTimestamp
GET /odata/Property?$orderby=ModificationTimestamp desc
GET /odata/Property?$orderby=ModificationTimestamp desc, ListPrice asc
Aggregation
There are two approaches to generating an aggregation result, using:
- using $apply=groupby()
- using $nested
OData standard protocol prefers usage of the former, however this does not appear to support nested aggregation results, thus there is the latter option.
Aggregation results are returned in the group:[] node, it is often useful to use the $top=0 flag to clear the value:[] results as this may not be needed during aggregation requests.
With $apply=groupby() multiple aggregate results can be returned provided a comma separated list.
Example requests:
GET /odata/Property?$apply=groupby((StateOrProvince))&$top=0
GET /odata/Property?$apply=groupby((StateOrProvince,City))&$top=0
Example results:
{
"@@odata.context":"https://listings.constellation1apis.com/$metadata#Property",
"@@odata.count":0,
"@@odata.totalCount":2590,
"value":[ ... ],
"group":[
{
"groupby":"StateOrProvince",
"count":3,
"buckets":[
{
"key":"IL",
"count":3,
"sub_aggregate":[
...
]
},
{
"key":"KY",
"count":2584,
"sub_aggregate":[
...
]
},
{
"key":"TN",
"count":3,
"sub_aggregate":[
...
]
}
]
}
]
}
Nested
In addition to the $apply=groupby() approach, the $nested approach can support nested results, it can also handle fields which are collection of strings.
Example requests:
GET /odata/Property?$nested=PropertyType,PropertySubType,ArchitecturalStyle
Example response:
{
"@@odata.context":"https://listings.constellation1apis.com/$metadata#Property",
"@@odata.count":0,
"@@odata.totalCount":10000,
"value":[
],
"group":[
{
"groupby":"PropertyType",
"count":21,
"buckets":[
{
"key":"CLE",
"count":95,
"sub_aggregate":[
{
"groupby":"PropertySubType",
"count":2,
"buckets":[
{
"key":"Business",
"count":1,
"sub_aggregate":[
{
"groupby":"ArchitecturalStyle",
"count":1,
"buckets":[
{
"key":"Other (see remarks)",
"count":1,
"sub_aggregate":[
]
}
]
}
]
},
{
"key":"Unimproved Land",
"count":3,
"sub_aggregate":[
{
"groupby":"ArchitecturalStyle",
"count":2,
"buckets":[
{
"key":"Other (see remarks)",
"count":2,
"sub_aggregate":[
]
},
{
"key":"Traditional",
"count":1,
"sub_aggregate":[
]
}
]
}
]
}
]
}
]
},
{
"key":"TWN",
"count":6,
"sub_aggregate":[
{
"groupby":"PropertySubType",
"count":1,
"buckets":[
{
"key":"Townhouse",
"count":6,
"sub_aggregate":[
{
"groupby":"ArchitecturalStyle",
"count":0,
"buckets":[
]
}
]
}
]
}
]
}
]
}
]
}
Time Range Queries
Queries can contain filter on date ranges for DateTime field types
Example Requests:
GET /odata/Property?$ignorenulls=true&$filter=ModificationTimestamp ge 2022-01-01T00:00:00Z
GET /odata/Property?$ignorenulls=true&$filter=ModificationTimestamp gt 2022-01-01T00:00:00Z and ModificationTimestamp lt 2022-02-01T00:00:00Z
How to do a full job?
A full job requires the first request to a sort by $orderby=ListingKey asc this acts as an initial marker to retrieve subsequent records via the @@odata.nextLink url
Example
First request:
GET /odata/Property?$ignorenulls=true&$filter=OriginatingSystemName eq 'CRMLS'&$top=300&$orderby=ListingKey asc
Use the @@odata.nextLink url returned from the first request for the rest of the requests:
GET /odata/Property/skiptoken/FGluY2x1ZGVfY29udGV4dF91dWlkDnF1ZXJ5VGhlbkZldGNoBRZGYmFTT0FSRVExeTRfckMxZ1loOEhnAAAAAAm0TVYWajZEYmttQ1JSWEdIUTlfRDRHNnB0dxY0NUZaQzBJcFI2NmU5N1h5NHFpWXZ3AAAAAAnwnR4WTVQ3WEhKLU9Ua215d2xxWW94SFcydxZGYmFTT0FSRVExeTRfckMxZ1loOEhnAAAAAAm0TVcWajZEYmttQ1JSWEdIUTlfRDRHNnB0dxY0NUZaQzBJcFI2NmU5N1h5NHFpWXZ3AAAAAAnwnR8WTVQ3WEhKLU9Ua215d2xxWW94SFcydxY0NUZaQzBJcFI2NmU5N1h5NHFpWXZ3AAAAAAnwnSAWTVQ3WEhKLU9Ua215d2xxWW94SFcydw==/?$filter=OriginatingSystemName%20eq%20%27CRMLS%27&$ignorenulls=true&$top=300
Keep cycling through the entire result set until the @@odata.count is 0
MLS Sync
We recommend a sync process be run once or twice per day in which you request all available ListingIds from a given data source. The delta between that list and the one you currently have in your database will signal which listings should be removed from your database, as well as flag any records available to you which may have been missed in regular incremental operations. This is the same method by which we keep the Constellation1 API current.
Example Requests:
GET /odata/Property?$ignorenulls=true&$select=ListingId
GET /odata/Property?$ignorenulls=true&$select=ListingKey,ListingId
Images
Retrieve images
There are two ways to retrive images:
- The recommended way to retrive image Urls is to use $expand on Property entity. In this way, you can get all the image records for one listing, and can use this data to compare with the records in your system to do the add/update/delete operations.
PhotosChangeTimestamp is the field in Property entity to reflect the last photo modification timestamp and can be used to get the list of listings with latest photo updates.
Example requests:
GET /odata/property?$ignorenulls=true&$expand=Media&$select=ListingId,PhotosCount&$filter=OriginatingSystemName eq 'CRMLS' and PhotosChangeTimestamp ge 2022-06-06T16:53:07+00:00
Example response:
{
"@@odata.context": "http://listings.constellation1apis.com/$metadata#Property",
"@@odata.count": 50,
"@@odata.totalCount": 70,
"value": [
{
"ListingId": "PW22122540",
"OriginatingSystemName": "CRMLS",
"PhotosCount": 4,
"StandardStatus": "Active",
"Media": [
{
"Id": "13071194064517",
"Order": 0,
"MediaType": "jpeg",
"MediaURL": "https://photos.prod.cirrussystem.net/1307/731c82121af9e429dfa966711c59b46d/2505719132.jpeg",
"MediaModificationTimestamp": "2022-06-08T01:51:13.103441Z",
"ModificationTimestamp": "2022-06-08T01:51:13+00:00",
"OriginatingSystemName": "CRMLS",
"ResourceRecordID": "PW22122540",
"MediaCategory": "Photo",
"ResourceRecordKey": "13074115592807",
"MediaKey": "13071194064517"
},
{
"Id": "13072357035296",
"Order": 1,
"MediaType": "jpeg",
"MediaURL": "https://photos.prod.cirrussystem.net/1307/731c82121af9e429dfa966711c59b46d/604979049.jpeg",
"MediaModificationTimestamp": "2022-06-08T01:51:13.1653589Z",
"ModificationTimestamp": "2022-06-08T01:51:13+00:00",
"OriginatingSystemName": "CRMLS",
"ResourceRecordID": "PW22122540",
"MediaCategory": "Photo",
"ResourceRecordKey": "13074115592807",
"MediaKey": "13072357035296"
},
{
"Id": "13073563813694",
"Order": 2,
"MediaType": "jpeg",
"MediaURL": "https://photos.prod.cirrussystem.net/1307/731c82121af9e429dfa966711c59b46d/510761608.jpeg",
"MediaModificationTimestamp": "2022-06-08T01:51:13.2318988Z",
"ModificationTimestamp": "2022-06-08T01:51:13+00:00",
"OriginatingSystemName": "CRMLS",
"ResourceRecordID": "PW22122540",
"MediaCategory": "Photo",
"ResourceRecordKey": "13074115592807",
"MediaKey": "13073563813694"
},
{
"Id": "1307524091547",
"Order": 3,
"MediaType": "jpeg",
"MediaURL": "https://photos.prod.cirrussystem.net/1307/731c82121af9e429dfa966711c59b46d/4053895032.jpeg",
"MediaModificationTimestamp": "2022-06-08T01:51:13.3700629Z",
"ModificationTimestamp": "2022-06-08T01:51:13+00:00",
"OriginatingSystemName": "CRMLS",
"ResourceRecordID": "PW22122540",
"MediaCategory": "Photo",
"ResourceRecordKey": "13074115592807",
"MediaKey": "1307524091547"
}
],
}
],
"group": [],
"@@odata.nextLink": "https://listings.constellation1apis.com/odata/property/skiptoken/FGluY2x1ZGVfY29udGV4dF91dWlkDnF1ZXJ5VGhlbkZldGNoBRZ6ZlBObmtkcVQwaVN1VUNMNC1nWHN3AAAAAAE873EWQi1OZTg5a0hRMXVwTXhmMUR6NWw2URZEUU9BblpIbVR1Nm5lOXBXT2FhaXh3AAAAAAFNXXEWcWkxY3hhUTRUcnFIMkZsZENwWktadxZjSWtRMl85ZlRaaTdFWVJsM0o1VjFRAAAAAAFTZWsWeHdfTmJXcDlSTW1fZVkxTVhjXzNWURZ6ZlBObmtkcVQwaVN1VUNMNC1nWHN3AAAAAAE873IWQi1OZTg5a0hRMXVwTXhmMUR6NWw2URZ6ZlBObmtkcVQwaVN1VUNMNC1nWHN3AAAAAAE873MWQi1OZTg5a0hRMXVwTXhmMUR6NWw2UQ==/?$expand=Media&$filter=OriginatingSystemName%20eq%20%27CRMLS%27%20and%20PhotosChangeTimestamp%20ge%202022-06-06T16%3A53%3A07.0000000Z%20and%20PhotosCount%20eq%204&$ignorenulls=true&$select=ListingId,PhotosCount,PhotosChangeTimestamp"
}
- Retrieve images from Media entity. Currently we only have the active photos in the Media entity. If a image is removed from the Media, you will not be able to find out unless you reference the PhotosCount in Property entity.
Example requests:
GET Example requests:
GET /odata/media?$filter=OriginatingSystemName eq 'CRMLS' and ModificationTimestamp gt 2022-06-08T18:08:18.5086332-07:00&$top=100&$ignorenulls=true
Example response:
{
"@@odata.context": "http://listings.constellation1apis.com/$metadata#Media",
"@@odata.count": 100,
"@@odata.totalCount": 40720,
"value": [
{
"Id": "1307474260391",
"Order": 0,
"MediaType": "jpeg",
"MediaURL": "https://photos.prod.cirrussystem.net/1307/aea51671d925e754134c87346ecb824b/141986726.jpeg",
"MediaModificationTimestamp": "2022-06-09T12:31:11.544528Z",
"ModificationTimestamp": "2022-06-09T12:31:16+00:00",
"OriginatingSystemName": "CRMLS",
"ResourceRecordID": "IV22118726",
"MediaCategory": "Photo",
"ResourceRecordKey": "13075796572",
"MediaKey": "1307474260391"
},
{
"Id": "13073608336386",
"Order": 1,
"MediaType": "jpeg",
"MediaURL": "https://photos.prod.cirrussystem.net/1307/aea51671d925e754134c87346ecb824b/19583124.jpeg",
"MediaModificationTimestamp": "2022-06-09T12:31:11.7175839Z",
"ModificationTimestamp": "2022-06-09T12:31:16+00:00",
"OriginatingSystemName": "CRMLS",
"ResourceRecordID": "IV22118726",
"MediaCategory": "Photo",
"ResourceRecordKey": "13075796572",
"MediaKey": "13073608336386"
},
{
"Id": "13072399412764",
"Order": 2,
"MediaType": "jpeg",
"MediaURL": "https://photos.prod.cirrussystem.net/1307/aea51671d925e754134c87346ecb824b/264290378.jpeg",
"MediaModificationTimestamp": "2022-06-09T12:31:11.8101757Z",
"ModificationTimestamp": "2022-06-09T12:31:16+00:00",
"OriginatingSystemName": "CRMLS",
"ResourceRecordID": "IV22118726",
"MediaCategory": "Photo",
"ResourceRecordKey": "13075796572",
"MediaKey": "13072399412764"
}
],
"group": [],
"@@odata.nextLink": "https://listings.constellation1apis.com/odata/media/skiptoken/FGluY2x1ZGVfY29udGV4dF91dWlkDnF1ZXJ5VGhlbkZldGNoBRZEUU9BblpIbVR1Nm5lOXBXT2FhaXh3AAAAAAFnDsoWcWkxY3hhUTRUcnFIMkZsZENwWktadxZ6ZlBObmtkcVQwaVN1VUNMNC1nWHN3AAAAAAFVQ_wWQi1OZTg5a0hRMXVwTXhmMUR6NWw2URZEUU9BblpIbVR1Nm5lOXBXT2FhaXh3AAAAAAFnDssWcWkxY3hhUTRUcnFIMkZsZENwWktadxZEUU9BblpIbVR1Nm5lOXBXT2FhaXh3AAAAAAFnDswWcWkxY3hhUTRUcnFIMkZsZENwWktadxZ6ZlBObmtkcVQwaVN1VUNMNC1nWHN3AAAAAAFVQ_0WQi1OZTg5a0hRMXVwTXhmMUR6NWw2UQ==/?$filter=OriginatingSystemName%20eq%20%27CRMLS%27%20and%20ModificationTimestamp%20gt%202022-06-09T01%3A08%3A18.5086332Z&$ignorenulls=true&$top=100"
}
Download Image By Url
Note: The iamge url represents one unique image based on the content of the image file, so you don't need download the image again if the url is the same.
Dowload original image by the url from the response:
https://photos.prod.cirrussystem.net/1307/731c82121af9e429dfa966711c59b46d/2505719132.jpeg
Download image by predefined sizes:
Add the parameter d={size} to the image url.Size values: l(Large, Width=1024), s(Small, Width=480), t(Thumbnail, Width=150)
Download thumbnail image example:
https://photos.prod.cirrussystem.net/1307/731c82121af9e429dfa966711c59b46d/2505719132.jpeg?d=t
Dynamic size image download:
-
By width only with d={Width}. Example:
https://photos.prod.cirrussystem.net/1307/731c82121af9e429dfa966711c59b46d/2505719132.jpeg?d=600 -
By width and height with d={Width}x{Height}. Exmaple:
https://photos.prod.cirrussystem.net/1307/731c82121af9e429dfa966711c59b46d/2505719132.jpeg?d=500x320