Rapattoni offers an implementation of RESO's Web API, and provides data adhering to the RESO Data Dictionary.
You will need to contact the particular MLS you wish to obtain data from, prior to access being granted.
We support OAuth2's Password and Authorization Code grant types for authentication.
Token URL:
https://retsidentityapi.raprets.com/{mls}/oauth/token
When accessing the Token URL, you will need to pass the following in the body of a POST request:
Please note, standard web browsers cannot pass all of the criteria; a client program or tool should be used. Example clients for testing are Postman and cURL
The body of the request should look similar to the following example:
grant_type=password&client_id=ClientID&client_secret=Secret&username=Username&password=Password
You will also need to include the header:Content-Type: application/x-www-form-urlencoded
and ensure that the values contained in the body of the request are properly URL-encoded.
cURL example:
curl -X POST -H "Content-Type:application/x-www-form-urlencoded" -d "Grant_Type=password&Client_Id=URLEncoded_ClientID&Client_Secret=URLEncoded_ClientSecret&Username=URLEncoded_Username&Password=URLEncoded_Password" "https://retsidentityapi.raprets.com/{mls}/oauth/token"
If the transaction is successful, then the response body will be a JSON object containing the access token, token type, seconds till expiration, refresh token, username, date time issued and date time of expiration. The token type will always be “bearer”:
"access_token": "9ad80cb9875c6d8e39efc90bc",
"token_type": "bearer",
"expires_in": 604799,
"refresh_token": "adb83739efc90bcd9938",
"userName": "username",
".issued": "Fri, 17 Mar 2017 16:41:32 GMT"
".expires": "Fri, 24 Mar 2017 16:41:32 GMT"
}
Authorization URL:
https://retsidentityapi.raprets.com/{mls}/oauth/authorize
You will need to pass the following information as query string parameters in a GET request with the Authorization URL.
https://retsidentityapi.raprets.com/{mls}/oauth/authorize?response_type=code&client_id=ClientID&redirect_uri=https://your_redirect_uri
Once the request has been sent, our server will respond with a login page to enter a valid MLS Username and Password. This could be information granted to you by the MLS, or it could be the login information of an agent utilizing your product.
If valid MLS credentials have been entered, then you, or the end user, will be prompted to grant your application access to the MLS API information on your/their behalf.
If successful we will pass the Authorization code and state (if included) in the query parameters of a GET request to your Redirect URI.
https://your_redirect_uri?code=authorization_code&state=the_state_string_if_used
You can then pass the following to the token end point to recieve a bearer token for API access:
Token URL:
https://retsidentityapi.raprets.com/{mls}/oauth/token
When accessing the Token URL, you will need to pass the following in the body of a POST request:
Please note, standard web browsers cannot pass all of the criteria; a client program or tool should be used. Example clients for testing are Postman and cURL
The body of the request should look similar to the following example:
grant_type=authorization_code&client_id=ClientID&client_secret=Secret&code=abc8393d9b8c7e8f03&redirect_uri=https://your_redirect
You will also need to include the header:Content-Type: application/x-www-form-urlencoded
and ensure that the values contained in the body of the request are properly URL-encoded.
If the transaction is successful, then the response body will be a JSON object containing the access token, token type, seconds till expiration, refresh token, username, date time issued, date time of expiration and your client_id. The token type will always be “bearer”:
"access_token": "9ad80cb9875c6d8e39efc90bc",
"token_type": "bearer",
"expires_in": 5183999,
"refresh_token": "adb83739efc90bcd9938",
".issued": "Tue, 10 Sep 2019 23:18:25 GMT",
".expires": "Sat, 09 Nov 2019 23:18:25 GMT",
"client_id": "ClientID"
}
All transactions must include the Authorization header with the value being the client’s current bearer token obtained from the transaction with our Authentication server.
Here is an example of the how the Authorization header with the bearer token should appear in the HTTP request:
Authorization:bearer 80957f49b90d449c99dfb01871676e3e
Responses, unless otherwise specified, will be in the JSON format.
The Service Document is available via a get request against the root URL (http://retsapi.raprets.com/{mls}/RESO/odata
). This document is a standard OData resource listing all top-level entity sets exposed by the service.( ODatav4 10.1)
Querying this endpoint will return a JSON array of all directly queryable entities. Each object will have the following properties:
{
"name": "Property",
"kind": "EntitySet",
"url": "Property"
},
{
"name": "Agents",
"kind": "EntitySet",
"url": "Agents"
},
The Metadata Document is available via a get request against the root URL with /$metadata
appended (i.e. http://retsapi.raprets.com/{mls}/RESO/odata/$metadata
). This resource describes the API’s data model; including data types, relationships between entity sets, and available fields (ODatav4 11.1.2). This resource is only available in the XML format.
Each entity definition will begin with the <EntityType> tag containing the Name of the entity.
<EntityType Name="Property">
<Key>
<PropertyRef Name="ListingKeyNumeric" />
</Key>
<Property Name="PrivateRemarks" Type="Edm.String" MaxLength="500" />
<Property Name="PropertyType" Type="PropertyEnums.PropertyType" MaxLength="20" />
<Property Name="Taxesannual" Type="Edm.Decimal" Precision="8" Scale="2">
<Annotation Term="RESO.OData.Metadata.MLSName" String="Taxes(annual)" />
</Property>
<NavigationProperty Name="ListingAgent" Type="Rapattoni.Rets.Api.Models.Agents" />
<NavigationProperty Name="PropertyPictures" Type="Collection(Rapattoni.Rets.Api.Models.Media)" />
Also included in the metadata are Enumeration definitions. An enumerated field will state it's defined enumeration in it's Type:
<Property Name="PropertyType" Type="PropertyEnums.PropertyType" MaxLength="20" />
The first portion of the Type, before the ".", defines the Schema Namespace in which the Enum resides. The second portion, after the ".", defines the EnumType name within the given Namespace.
<Schema Namespace="PropertyEnums" xmlns:edm="http://docs.oasis-open.org/odata/ns/edm">
<EnumType Name="PropertyType" UnderlyingType="Edm.Int32">
<Member Name="CommercialLease" Value="0">
<Annotation Term="RESO.OData.Metadata.StandardName" String="Commercial Lease" />
</Member>
<Member Name="CommercialSale" Value="1">
<Annotation Term="RESO.OData.Metadata.StandardName" String="Commercial Sale" />
</Member>
<Member Name="Land" Value="2" />
<Member Name="MultiUnit" Value="3">
<Annotation Term="RESO.OData.Metadata.MLSName" String="Multi-Unit" />
</Member>
<Member Name="Rental" Value="4">
<Annotation Term="RESO.OData.Metadata.StandardName" String="Residential Lease" />
</Member>
<Member Name="Residential" Value="5" />
</EnumType>
The DataSystem endpoint will list all available Resources and required Class values. The Localization arrary will contain the available Classes.
Example DataSystem:
Query: http://retsapi.raprets.com/{mls}/RESO/odata/DataSystem
Results:
{
"@odata.context": "http://retsapi.raprets.com/{mls}/RESO/OData/$metadata#DataSystem/$entity",
"Id": 1,
"Mls": "mls",
"Name": "Rapattoni Rets",
"ServiceUri": "http://retsapi.raprets.com/{mls}/RESO/OData",
"DateTimeStamp": "2017-03-16T10:18:19.26-07:00",
"TransportVersion": "1.0.2",
"DataDictionaryVersion": "1.6",
"Resources": [
{
"Id": 1,
"DataSystemId": 1,
"Name": "Property",
"ResourcePath": "/Property",
"Description": "The property endpoint",
"DateTimeStamp": "2016-07-11T14:20:13.863-07:00",
"TimeZoneOffset": 0,
"Localization": [
{
"Name": "Land",
"ResourcePath": "/Property?Class=Land",
"Description": "Contains data for Land searches.",
"DateTimeStamp": "2017-11-07T18:16:43.1-08:00"
},
{
"Name": "Residential",
"ResourcePath": "/Property?Class=Residential",
"Description": "Contains data for Residential searches.",
"DateTimeStamp": "2017-11-07T18:16:43.1-08:00"
}
]
},
{
"Id": 2,
"DataSystemId": 1,
"Name": "Agent",
"ResourcePath": "/Agents",
"Description": "The agent endpoint",
"DateTimeStamp": "2016-07-11T14:20:13.863-07:00",
"TimeZoneOffset": 0,
"Localization": [
{
"Name": "Member",
"ResourcePath": "/Agents?Class=Member",
"Description": "Contains data for Agent searches.",
"DateTimeStamp": "2017-07-18T23:12:38.953-07:00"
}
]
}
]
}
Entity Set Queries:Entity Set queries use the default OData format; the root URL is appended with “/EntitySet”. The ResourcePath elements returned from the DataSystem query are the exact entity set values to use. Queries against any entity set MUST include the Class query argument; the Classes available for each entity set are available via the DataSystem endpoint in the Localization array (see above DataSystem example). The following URL would be used for querying the Property entity set and the Residential Class:
http://retsapi.raprets.com/{mls}/RESO/OData/Property?Class=Residential
When Querying against Entity Sets, our implementation of the RESO Web API supports most OData 4 query options, functions and operators. The below list are those query options and some of their associated supported functions and operators. Please see the OData 4 specification for further information in regards to these:
Property?Class=Residential&$filter=MlsStatus eq 'Active'&$select=ListingKeyNumeric,City&$top=10
http://retsapi.raprets.com/{mls}/RESO/OData/Property(101)?Class=Residential
http://retsapi.raprets.com/{mls}/RESO/OData/Property?Class=Residential&$select=ListingKeyNumeric,ListingId,StandardStatus,City
http://retsapi.raprets.com/{mls}/RESO/OData/Property?Class=Residential&$filter=StandardStatus eq 'Active'
http://retsapi.raprets.com/{mls}/RESO/OData/Property?Class=Residential&$filter=City ne 'Granite Bay'
http://retsapi.raprets.com/{mls}/RESO/OData/Property?Class=Residential&$filter=BathroomsTotalInteger gt '2'
http://retsapi.raprets.com/{mls}/RESO/OData/Property?Class=Residential&$filter=BathroomsTotalInteger lt '2'
http://retsapi.raprets.com/{mls}/RESO/OData/Property?Class=Residential&$filter=BathroomsTotalInteger lt '2' and City eq 'San Francisco'
http://retsapi.raprets.com/{mls}/RESO/OData/Property?Class=Residential&$filter=BathroomsTotalInteger lt '2' or City eq 'San Francisco'
http://retsapi.raprets.com/{mls}/RESO/OData/Property?Class=Residential&$filter=BathroomsTotalInteger lt '2' and not City eq 'San Francisco'
http://retsapi.raprets.com/{mls}/RESO/OData/Property?Class=Residential&$filter=BathroomsTotalInteger lt '2' or (City eq 'San Francisco' and MlsStatus eq 'Sold')
http://retsapi.raprets.com/{mls}/RESO/OData/Property?Class=Residential&$filter=ListingTerms has Rapattoni.Rets.Api.Models.ListingTerms'Cash'
http://retsapi.raprets.com/{mls}/RESO/OData/Property?Class=Residential&$filter=geo.distance(Location, geography'POINT(-79.209274 37.388645)') lt 1000
Property?Class=Residential$filter=(contains(PublicRemarks,‘pool’) and City eq ‘Ventura’) or ListingTerms has Rapattoni.Rets.Api.Models.ListingTerms'Cash'
http://retsapi.raprets.com/{mls}/RESO/OData/Property?Class=Residential&$top=10
http://retsapi.raprets.com/{mls}/RESO/OData/Property?Class=Residential&$skip=100
http://retsapi.raprets.com/{mls}/RESO/OData/Property?Class=Residential&$orderby=City desc
http://retsapi.raprets.com/{mls}/RESO/OData/Property?Class=Residential&$orderby=Status asc
http://retsapi.raprets.com/{mls}/RESO/OData/Property?Class=Residential&$count=true
http://retsapi.raprets.com/{mls}/RESO/OData/Property?Class=Residential&$apply=groupby((City))
Property?Class=Residential&$expand=PropertyPictures
: this will return Residential Property records and their related entries from Media's PropertyPictures class.Prefer:odata.maxpagesize=50
Columns Selected | Resource(Entity) | Time of Day | Page Size |
---|---|---|---|
1-4 | Any Except Media | Any | 1000000 |
1-4 | Media | Any | 100000 |
5-50 | Any | Any | 2000 |
51+ | Any | 8am-6pm | 1000 |
51+ | Any | 6:01pm-7:59am | 2000 |