{
"openapi": "3.0.4",
"info": {
"title": "REALTOR.ca DDF® Web API Documentation",
"description": "\r\nThe REALTOR.ca Data Distribution Facility (DDF®) allows REALTORS® across Canada to access listing content\r\non personal websites, franchisor websites, real estate advertising websites and partner sites based on\r\npermissions set by their brokerage owner. REALTOR.ca DDF® manages these permissions and provides\r\nREALTORS® with the ability to create data feeds based off these permissions.\r\n\r\nThe REALTOR.ca DDF® Web API is a data distribution platform that allows CREA Members, Developers and\r\nTech Providers data access using APIs built on modern industry standards. The platform standardizes how\r\nyou access MLS® System listing data received from boards and associations across Canada. MLS® System\r\ndata is normalized based on the RESO Data Dictionary standards.\r\n\r\nThe DDF® Web API data and endpoints are behind an authentication layer that requires a valid\r\naccess_token. To access the Web API data or endpoints, include access_token with each call made to the\r\nAPI. The access_token can be generated by using your data feed credentials and making a call to our\r\nauthentication server.\r\n\r\n# Quickstart Overview \r\n\r\nThis quickstart example will walk you through requesting the access_token and accessing the DDF® Web API endpoints by making API calls. \r\n\r\nFor this guide, you can use any API client of your choice. \r\n\r\n### Prerequisites \r\n\r\nTo run this quickstart, you need the following prerequisites: \r\n\r\n- API Client of your choice\r\n- client_id - your data feed's username\r\n- client_secret - your data feed's password\r\n\r\n\r\n\r\n### Step 1 - Get an access token \r\n\r\nAn access token is required to make requests to DDF® Web API. To generate one, make a request to identity.crea.ca. The access token lasts for 60 minutes. \r\n\r\n**Example Request:** \r\n\r\n\tPOST /connect/token \r\n\tHost: identity.crea.ca \r\n application/x-www-form-urlencoded\r\n\r\n Body\r\n\tgrant_type : \"client_credentials\"\r\n\tclient_id : \"xxxxxxxx\"\r\n\tclient_secret : \"xxxxxxxx\"\r\n\tscope : \"DDFApi_Read\"\r\n\r\n**Example Response:**\r\n\r\nThe response includes the access_token. This is what you will use to make API calls to DDF® Web API.\r\n\r\n```json\r\n{\r\n \"access_token\": \"{access_ token}\",\r\n \"expires_in\": 3600,\r\n \"token_type\": \"Bearer\",\r\n \"scope\": \"DDFApi_Read\"\r\n}\r\n```\r\n\r\n\r\n### Step 2 - Make an API call to any resource available \r\n\r\nProceed making an API call to our OpenHouse endpoint in DDF® Web API using the access_token that was generated in the previous step. \r\n\r\n**Example Request:**\r\n\r\n\tGET /odata/v1/OpenHouse \r\n\tHost: ddfapi.realtor.ca \r\n\tAuthorization: Bearer {access_token} \r\n\r\n**Example Response:** \r\n\r\nStatus: 200 OK \r\n```json\t\r\n{\r\n \"@odata.context\": \"https://ddfapi.realtor.ca/odata/v1/$metadata#OpenHouse\",\r\n \"value\": [{\r\n \"OpenHouseKey\": \"1000\",\r\n \"OpenHouseStartTime\": \"21:04:51.25\",\r\n \"OpenHouseEndTime\": \"21:04:51.25\",\r\n \"ListingKey\": \"22009401\",\r\n \"ListingId\": \"ListingIdSample\",\r\n \"OpenHouseDate\": \"2021-07-12\",\r\n \"OpenHouseRemarks\": \"OpenHouseRemarksSample\",\r\n \"ShowingAgentFirstName\": \"ShowingAgentFirstnameSample\",\r\n \"ShowingAgentLastName\": \"ShowingAgentLastNameSample\",\r\n \"ShowingAgentKey\": \"2000\",\r\n \"ShowingAgentMlsID\": \"ShowingAgentMlsIDSample\",\r\n \"OpenHouseType\": \"Sheetrock (Drywall)\",\r\n \"OpenHouseStatus\": \"Off Market\"\r\n }\r\n ]\r\n}\r\n```\r\n\r\n\r\n### Step 3 - Make an API call with OData capabilities \r\n\r\nOur DDF® Web API was built on top of OData specification, this gives users the ability to query our resources in a more flexible way. \r\n\r\n**Example Request:**\r\n\r\n\tGET /odata/v1/OpenHouse?$select=OpenHouseKey \t\r\n\tHost: ddfapi.realtor.ca \r\n \tAuthorization: Bearer {access_token} \r\n\r\nThe request above returns Open House records but only the OpenHouseKey field in the payload based on the $select criteria. \r\n\r\n**Example Response:**\r\n\r\nStatus: 200 OK \r\n```json\r\n{\r\n \"@odata.context\": \"https://ddfapi.realtor.ca/odata/v1/$metadata#OpenHouse(OpenHouseKey)\",\r\n \"value\": [{\r\n \"OpenHouseKey\": \"1000\"\r\n }, {\r\n \"OpenHouseKey\": \"1001\"\r\n }, {\r\n \"OpenHouseKey\": \"1002\"\r\n }\r\n ]\r\n}\r\n```\r\n\r\n\r\n\r\n\r\n\r\n# Authorization\r\n\r\nAuthorization for the DDF® Web API platform is done through an Identity Server. The Identity Server leverages OAUTH 2.0 to provide access tokens to DDF® Web API. \r\n\r\n## API Access Tokens \r\n\r\nAll data access for an application is authorized and authenticated using API tokens. \r\n\r\nFor DDF® Web API we recommend using a server token to implement server-to-server API requests. Client-to-server API token requests create a security risk and could allow unauthorized access to your data feeds. \r\n\r\nEach request to the DDF® Web API requires an active data feed with valid credentials to obtain an access token. An inactive feed will result in no access token returned. \r\n\r\nTo request a token, send a POST request to the following endpoint. \r\n\r\n https://identity.crea.ca/connect/token \r\n\r\nThe following fields should be in the request body and should be x-www-form-urlencoded. \r\n\r\n| Field | Description | \r\n| ----------- | ----------- |\r\n| client_id | The username of your Destination |\r\n| client_secret | The password of your Destination |\r\n| grant_type | Use the value client_credentials |\r\n| scope | Use the value DDFApi_Read |\r\n\r\nThe response will have the following fields when successful \r\n\r\n
| Field | \r\nDescription | \r\n
|---|---|
access_token | \r\n The value of the requested access token | \r\n
expires_in | \r\n The time in which the token expires (in seconds). Should be 3600 by default. NOTE: The token supplied is not a sliding token. After one hour a new token must be requested regardless. | \r\n
token_type | \r\n The type of token. Should always be Bearer. | \r\n
scope | \r\n Should always be DDFApi_Read | \r\n
OfficeKey) /Office/OfficeKey|\r\n| Office | Supplies replication data for Office.| Office/OfficeReplication |\r\n| Member | Supplies a list of Member data.| /Member |\r\n| Member | Supplies a single Member data.| /Member(MemberKey) /Member/MemberKey|\r\n| Member | Supplies replication data for Member.| /Member/MemberReplication |\r\n| Property | Supplies a list of Property data. | /Property|\r\n| Property | Supplies a single Property data. | /Property(PropertyKey) /Property/PropertyKey|\r\n| Property | Supplies replication data for Property. | /Property/PropertyReplication|\r\n| OpenHouse | Supplies OpenHouse data for specific listings. |/OpenHouse |\r\n| OpenHouse | Supplies a single OpenHouse data for specific listings. |/OpenHouse(OpenHouseKey) /OpenHouse/OpenHouseKey |\r\n| Destination | Supplies a list of Data Feed data. | /Destination |\r\n| Destination | Supplies a single Data Feed data. | /Destination(DestinationId) /Destination/DestinationId |\r\n\r\nAll endpoints are accessible through an authorization layer described in the next section. For a full description of the API endpoints, see the [API definition](#tag/Member). \r\n\r\n\r\n\r\n\r\n\r\n## API Response \r\n\r\nAll API responses are returned in json format with exception of metadata which are returned as XML. \r\n\r\nThe API response can contain a single or multiple data records. For complete details of data models in the API see the [Models](#tag/member_model) section of the API Definition. \r\n\r\n\r\n\r\n## Paginating through results \r\n\r\nIn order to minimize the data returned in a single query, results are paginated. By default, a page will contain a maximum of 20 results. This value can be increased using the $top query parameter which can increase the page size to a maximum of 100 records. \r\n\r\nIf an additional page of data beyond the current page exists, a field named @odata.nextLink will be returned in the response. The nextLink value will be a URL pointing to the next page of data. \r\n\r\n**Example Response:**\r\n```json\r\n{ \r\n\t\"@odata.context\": \"https://ddfapi.realtor.ca/odata/v1/$metadata#Member\", \r\n\t\"value\": [...], \r\n\t\"@odata.nextLink\": \"https://ddfapi.realtor.ca/odata/v1/Member?$top=20&$skip=20\" \r\n} \r\n```\r\n*Notice that the $top and $skip OData query parameters are used to select which page of data is selected in the next link.*\r\n\r\nIn order to determine total amount of pages, the $count query parameter should be used to retrieve the total amount of records which should be divided by the page size. **Note** that the $count parameter increases the overhead of a request therefore it is recommended that the total count of the data is requested once and not for each request of a page. \r\n\r\nWhen paginating through records, it is necessary to sort the results as there is no guarantee on the order, and multiple pages may include the same record more than once. \r\n\r\nIf you wish to paginate through more than 10,000 listings you will need to use the dedicated replication endpoint. \r\n\r\n\r\n\r\n## Replication \r\n\r\nThe purpose of the replication endpoints is to give technical providers the ability to easily replicate their data into their own separate database. The following endpoints are used for replication: \r\n\r\n```\r\nhttps://ddfapi.realtor.ca/Office/OfficeReplication \r\n\r\nhttps://ddfapi.realtor.ca/Member/MemberReplication \r\n\r\nhttps://ddfapi.realtor.ca/Property/PropertyReplication \r\n```\r\n\r\nThe described endpoints have the sole purpose of giving quick access to the records that have been updated most recently. They are sorted by a modification timestamp which should allow external systems to synchronize data periodically and check the records that have changed since the last run.\r\n\r\n\r\n\r\n## Testing Requests\r\n\r\nTo test any request in the Web API you will need to send an access token which cannot be done through a typical web browser. Postman (https://www.postman.com/) is the preferred option to quickly test out any request in the API however there are other tools available that may be your preference. Below are a few screenshots taken from Postman that outline typical requests.\r\n\r\n### Requesting A Token\r\n\r\n\r\n\r\n### Requesting A Property\r\n\r\n\r\n\r\n\r\n\r\n\\* **NOTE:** Minimum TLS version supported will be TLS v1.2. All incoming requests are expected to be from HTTPS to support TLS v1.2.\r\n\r\n## DDF® clients guide \r\n\r\nREALTOR.ca DDF® Web API platform allows DDF® clients to request and receive a parallel set of CREA data that will be displayed on their websites. The parallel data set must be refreshed regularly as CREA adds, updates, and deletes its records. \r\n\r\nThe set of records available to DDF® clients is rules-based and determined by \r\n\r\n- the type of destination making the request, \r\n- the owner of the destination, and \r\n- the approval settings of boards/associations, brokerage owners and/or salespersons (where applicable). \r\n\r\n### Step 1. Retrieve all the active records (Initial load) \r\n\r\nClients are advised to fetch the complete property details from the Property endpoint only for the first time. \r\n\r\n**Example:**\r\n```\r\nhttps://ddfapi.realtor.ca/odata/v1/Property \r\n```\r\n\r\n\r\n### Step 2. Retrieve all active records updated since a specified date/time. \r\n\r\nClients are advised against retrieving complete property details for all active records on every request. It is recommended that clients only request records updated since the last request was made. \r\n\r\nUse the replication endpoint to fetch all active records updated since the last request. \r\n\r\n**Example:**\r\n```\r\nhttps://ddfapi.realtor.ca/odata/v1/Property/PropertyReplication()?$filter=ModificationTimestamp gt 2024-01-25T00:00:00.00Z\r\n```\r\n\r\n### Step 3. Retrieve a master list of all active records. \r\n\r\nClients can obtain a comprehensive list of all records available through the Replication endpoint. Any properties, offices, or agents present in a customer's data store but not included in the master list must be removed from the customer's data store. For instance, only properties currently active on the market and approved for distribution will be included in the master list. If a property is no longer available on the market (due to being sold, cancelled, etc.), it will be excluded from the master list and should be deleted from the customer's data store. Additionally, the master list can be utilized to ensure the accuracy and consistency of the data. \r\n\r\nThe master list will contain 2 values for each record: the ListingKey and the ModificationTimestamp. \r\n\r\n**Example:**\r\n```\r\nhttps://ddfapi.realtor.ca/odata/v1/Property/PropertyReplication()\r\n```\r\n\r\n\r\n### Step 4. Retrieve Property details by Listing Key.\r\n\r\nAfter obtaining the ListingKeys of updated properties from the Replication endpoint, clients can utilize these ListingKeys to query the Property endpoint and retrieve the corresponding property details. \r\n\r\n**Example:**\r\n```\r\nhttps://ddfapi.realtor.ca/odata/v1/Property('4143136')\r\n```\r\n\r\n\r\n\r\n## Technology Provider guide \r\n\r\nDDF® Technology Providers are organizations that pull multiple data feeds for different users. These feeds can be of any type that agents and brokerage owners can register: Member Website Feeds – My Listings, Member Website Feed - All Offices, National Shared Pool. \r\n\r\nWhile these data feeds can be pulled separately, this creates 2 problems for Technology Providers: \r\n\r\nLastUpdated query, they will receive matching properties from any of their linked data feeds. Whether a property is available on only a single linked data feed or hundreds of linked data feeds, the Technology Provider will only need to retrieve that property details a single time. \r\n\r\nClients can retrieve a master list of the complete set of records accessible from the Replication endpoint. This list contains 2 values for each record: the ListingKey and the ModificationTimestamp. By comparing the timestamp, it is possible to identify any records that need to be updated or inserted. This will always return a complete list of records. \r\n\r\n**Example:**\r\n\r\n```\r\nhttps://ddfapi.realtor.ca/odata/v1/Property/PropertyReplication()?$filter=ModificationTimestamp gt 2024-01-25T00:00:00.00Z\r\n```\r\n\r\nAfter obtaining the ListingKeys of updated properties from the Replication endpoint, the Technology provider can utilize these ListingKeys to query the Property endpoint and retrieve the corresponding property details. \r\n\r\n**Example:**\r\n```\r\nhttps://ddfapi.realtor.ca/odata/v1/Property?$filter=ListingKey in ('123456','67891011')\r\n```\r\n\r\n**Retrieve a master list of all active records available in TP’s unified feed.**\r\n\r\nAs with standard DDF® data feeds, performing a daily Master List call is necessary to ensure that all properties are appropriately updated and to inform clients about properties that should be deleted from their systems. When a Technology Provider makes a Master List query, they receive a comprehensive list of all properties available in any of their linked feeds. \r\n\r\nIt is crucial that any properties, offices, or agents present in a client's data store but not found in the master list are promptly deleted from the client data store. For instance, the master list includes active properties that are approved for distribution in the market. If a property is no longer on the market (sold, cancelled, etc.), it will be excluded from the master list and should be removed from the client data store as well. The master list can also be used to ensure data integrity, as it serves as a reference for verifying the accuracy and consistency of the client's data. \r\n\r\n\r\n\r\nTechnology Provider Master List - **Example:**\r\n```\r\nhttps://ddfapi.realtor.ca/odata/v1/Property/PropertyReplication() \r\n```\r\n\r\n**Destination Endpoint**\r\n\r\nFor Technology Providers to query Master Lists for their clients, they must have knowledge of the DestinationID associated with each of their data feed clients. To facilitate this, a Destination endpoint is provided to Technology Providers, allowing them to retrieve information about each destination/data feed that is linked to them.\r\n\r\n- To retrieve all destinations associated with your Technology Provider account: \r\n\r\n**Example:** \r\n```\r\nhttps://ddfapi.realtor.ca/odata/v1/Destination\r\n```\r\n\r\n- To retrieve details of a **single** destination associated with your Technology Provider account: \r\n\r\n**Example:**\r\n```\r\nhttps://ddfapi.realtor.ca/odata/v1/Destination({DestinationKey})\r\n```\r\n\r\n**Retrieve the Property list per Destination.**\r\n\r\nThe ability of Technology Providers to get up-to-date properties for all their clients in a single feed is only part of the process. The next step is determining which properties go with the corresponding data feed client. For example, a single property may be displayed on Client A’s member website, and Client B’s National Shared Pool site, but shouldn’t be displayed on Client C’s National Shared Pool site because that client only receives properties from a single province. \r\n\r\nTo determine the relationship between properties and data feed clients, Technology Providers are required also to pull the Master List for each Destination. This can be accomplished by making a Master List query from the Replication endpoint with an optional DestinationID parameter included. \r\n\r\n- Master List for Client A: \r\n\r\n**Example:**\r\n```\r\nhttps://ddfapi.realtor.ca/odata/v1/Property/PropertyReplication(DestinationId=12517)\r\n```\r\n\r\n- Master List for Client B:\r\n\r\n**Example**\r\n```\r\nhttps://ddfapi.realtor.ca/odata/v1/Property/PropertyReplication(DestinationId=15019)\r\n```\r\n\r\n\r\n\r\n## Website requirements\r\n\r\n**Powered by: REALTOR.ca logo** \r\n\r\nDDF® Rules mandate that all DDF® Listing Content displayed on Real Estate Advertising Websites, Partner Sites, and Member Websites must include the \"Powered by REALTOR.ca\" badge. The badge should be clickable and redirected to the original listing on REALTOR.ca. \r\n\r\nIf REALTORS® are not using a DDF® Technology Provider and are managing their website, they will be responsible for ensuring the badge is on every listing. \r\n\r\nUse the following code snippets to embed \"Powered by: REALTOR.ca\" logos and links into your site. \r\n\r\n- **English -** \\ \\
</a> \r\n- **French -** \\ \\
</a> \r\n\r\n\r\n\r\n## Analytics \r\n\r\nGiven that a single listing can be displayed on numerous websites and applications, agents and brokerage owners require a means to track where their listing data is accessed. To address this, CREA has developed a data warehousing solution that enables comprehensive listing activity data collection. This data is categorized based on various factors, including the site or application, listing agent, firm, brokerage owner, and franchisor, providing agents and brokerage owners with valuable insights into the visibility and reach of their listings. \r\n\r\n**Analytics Web Service**\r\n\r\nThe analytics web service is used to capture listing statistics from various sources. Whenever a listing event occurs (e.g. a listing is viewed), the website or application should request the Analytics Web Service to record the event. No response handling is required, so these requests may be made asynchronously. \r\n\r\n**End Point -** https://analytics.crea.ca/LogEvents.svc/LogEvents \r\n\r\n**Request Arguments**\r\n\r\n| ListingID | Integer | The [ListingID] parameter in the Analytics Web service is a unique identifier for the record, known as [ListingKey] in the Web API according to RESO standards. | Yes | | \r\n| DestinationID | Integer | ID of the Destination | Yes | Destination ID of the DDF® data feed where the event occurs. |\r\n| EventType | String | Event tracked by analytics | Yes | See Event Types section below. | \r\n| UUID | String | Unique Identifier of the user/device. This ID should be the same for all requests from a single user/device. | Yes | GUID or device identifier with the Destination ID appended.IP | IP Address | If available, IP address of the client or device | No | *Note: this parameter is used to resolve geographic data. If it is not supplied this information will not be resolved.* | \r\n| ReferralURL | URL | This URL is validated during the analytics processing. | No | | \r\n| LanguageID | Integer | Language being used by the user | No | 1 = English | Template | \r\n\r\n \r\n https://analytics.crea.ca/LogEvents.svc/LogEvents?ListingID={ListingID}&DestinationID={DestinationID}&EventType={EventType}&UUID={UUID}&IP={IP}&ReferralURL={ReferralURL}\r\n\r\n |
| Example | \r\n\r\n \r\n https://analytics.crea.ca/LogEvents.svc/LogEvents?ListingID=12830763&DestinationID=355&EventType=view&UUID=6b106320-b422-11e2-9e96-0800200c9a66-355&IP=192.168.1.1&ReferralURL=http://samplesite.com\r\n \r\n |
| Name | \r\nDescription | \r\nExample | \r\n
|---|---|---|
$skip | \r\n Skips this number of results. | \r\n\r\n Skip the first 10 records of the Property dataset. \r\n https://ddfapi.realtor.ca/odata/v1/Property?$skip=10\r\n | \r\n
$select | \r\n Select the fields to be returned. | \r\n\r\n Only return the ListingKey and PropertySubType fields. \r\n https://ddfapi.realtor.ca/odata/v1/Property?$select=ListingKey,PropertySubType\r\n | \r\n
$filter | \r\n Filter the results to be returned. | \r\n\r\n Only return the listings where the ListPrice is greater than $100,000. \r\n https://ddfapi.realtor.ca/odata/v1/Property?$filter=ListPrice%20gt%20100000\r\n | \r\n
$top | \r\n Limits the size of the result set. | \r\n\r\n Default is 20, maximum is 100. Limit results from the Property dataset to only 2. \r\n https://ddfapi.realtor.ca/odata/v1/Property?$top=2\r\n | \r\n
$orderby | \r\n Sort the result by descending or ascending order (either “desc” or “asc”). | \r\n\r\n Sort order by descending price. \r\n https://ddfapi.realtor.ca/odata/v1/Property?$orderby=ListPrice%20desc\r\n | \r\n
eq | Equal | \r\n| ne | Not equal |\r\n| gt | Greater than |\r\n| lt | Less than |\r\n| ge | Greater than or equal |\r\n| le | Less than or equal |\r\n| and | Logical and |\r\n| or | Logical or |\r\n| not | Logical not |\r\n| in | In |\r\n| has | Has |\r\n\r\n*More information on OData operators can be found [here](http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part2-url-conventions/odata-v4.0-errata03-os-part2-url-conventions-complete.html#_Toc453752358).*\r\n\r\n\r\n\r\n## OData Query Functions \r\n\r\n| Function | Description | Example |\r\n| ----------- | ----------- | ----------- |\r\n| any | Search fields where any element of an array is satisfied by a condition. This operand will work with Collection and complex types. | Return listings where there is an option of electric heating.