Back to top

API Documentation

Portals

Overview

A Portal represents a public-facing surface for a brand, optionally tied to a lead channel. A brand has at most one portal; portals are created explicitly via the create endpoint.

Field Type Association Description
id uuid Internal identifier of the portal
brand uuid brands(id) Brand to which this portal belongs
lead_channel uuid lead_channels(id) Optional lead channel attached to this portal
token uuid Authentication token for this portal
hostnames string[] Hostnames associated with this portal (default first)
created_at number Timestamp of when this portal was created
updated_at number Timestamp of when this portal was last updated
deleted_at number Timestamp of when this portal was deleted (if applicable)

Ensure a brand has a portal

Ensure a brand has a portal
PUT/brands/:brand/portal

Idempotent — returns the brand’s existing portal if there is one, otherwise creates one and returns it. The new portal’s lead_channel defaults to the brand’s default lead channel (which itself is created on demand if missing).

brand (uuid) ID of the brand

Example URI

PUT /brands/:brand/portal
URI Parameters
HideShow
brand
string (required) Example: 4c3970ea-d648-4b25-baa8-8f7af73f318c
associations
string (required) Example: portal.brand
Response  200
HideShow
Body
{
  "code": "OK",
  "data": {
    "id": "996a4087-4141-40f3-94cd-49d6462af666",
    "brand": {
      "id": "4c3970ea-d648-4b25-baa8-8f7af73f318c",
      "created_at": 1778872278.764919,
      "updated_at": 1778872278.764919,
      "palette": null,
      "assets": null,
      "messages": null,
      "parent": null,
      "name": "PortalTestBrand",
      "deleted_at": null,
      "training": false,
      "brand_type": "Brokerage",
      "parents": null,
      "type": "brand",
      "hostnames": null,
      "member_count": 1,
      "base_url": "https://irish.rechat.com"
    },
    "type": "portal",
    "created_at": 1778872279.349493,
    "updated_at": 1778872279.349493,
    "deleted_at": null,
    "hostnames": null
  }
}

Get the portal of a brand

Get the portal of a brand
GET/brands/:brand/portal

Read-only. Returns 404 if the brand has no portal yet — use PUT to create one.

brand (uuid) ID of the brand

Example URI

GET /brands/:brand/portal
URI Parameters
HideShow
brand
string (required) Example: 4c3970ea-d648-4b25-baa8-8f7af73f318c
associations
string (required) Example: portal.brand
Response  200
HideShow
Body
{
  "code": "OK",
  "data": {
    "id": "996a4087-4141-40f3-94cd-49d6462af666",
    "brand": {
      "id": "4c3970ea-d648-4b25-baa8-8f7af73f318c",
      "created_at": 1778872278.764919,
      "updated_at": 1778872278.764919,
      "palette": null,
      "assets": null,
      "messages": null,
      "parent": null,
      "name": "PortalTestBrand",
      "deleted_at": null,
      "training": false,
      "brand_type": "Brokerage",
      "parents": null,
      "type": "brand",
      "hostnames": null,
      "member_count": 1,
      "base_url": "https://irish.rechat.com"
    },
    "type": "portal",
    "created_at": 1778872279.349493,
    "updated_at": 1778872279.349493,
    "deleted_at": null,
    "hostnames": null
  }
}

Look up a portal by hostname

Look up a portal by hostname
GET/portals/search{?hostname}

hostname (string) Hostname to look up; must be at least 5 characters

Example URI

GET /portals/search?hostname=portal-testhost
URI Parameters
HideShow
hostname
string (required) Example: portal-testhost
Response  200
HideShow
Body
{
  "code": "OK",
  "data": {
    "id": "996a4087-4141-40f3-94cd-49d6462af666",
    "type": "portal",
    "created_at": 1778872279.349493,
    "updated_at": 1778872279.349493,
    "deleted_at": null,
    "hostnames": [
      "portal-testhost"
    ]
  }
}

Portal Hostnames

Add a hostname to a brand's portal

Add a hostname to a brand's portal
POST/brands/:brand/portal/hostnames

brand (uuid) ID of the brand whose portal to add the hostname to.

hostname (string) Hostname to attach

is_default (boolean) Whether this hostname should be the default for the portal

Example URI

POST /brands/:brand/portal/hostnames
URI Parameters
HideShow
brand
string (required) Example: 4c3970ea-d648-4b25-baa8-8f7af73f318c
Request
HideShow
Body
{
  "hostname": "portal-testhost",
  "is_default": true
}
Response  200
HideShow
Body
{
  "code": "OK",
  "data": {
    "id": "996a4087-4141-40f3-94cd-49d6462af666",
    "type": "portal",
    "created_at": 1778872279.349493,
    "updated_at": 1778872279.349493,
    "deleted_at": null,
    "hostnames": [
      "portal-testhost"
    ]
  }
}

Remove a hostname from a brand's portal

Remove a hostname from a brand's portal
DELETE/brands/:brand/portal/hostnames{?hostname}

brand (uuid) ID of the brand whose portal to remove the hostname from.

hostname (string) Hostname to detach

Example URI

DELETE /brands/:brand/portal/hostnames?hostname=portal-testhost
URI Parameters
HideShow
brand
string (required) Example: 4c3970ea-d648-4b25-baa8-8f7af73f318c
hostname
string (required) Example: portal-testhost
Response  200
HideShow
Body
{
  "code": "OK",
  "data": {
    "id": "996a4087-4141-40f3-94cd-49d6462af666",
    "type": "portal",
    "created_at": 1778872279.349493,
    "updated_at": 1778872279.349493,
    "deleted_at": null,
    "hostnames": null
  }
}

Portal Saved Searches

These endpoints are authenticated by the portal’s own token rather than a bearer credential. Pass the token in the X-RECHAT-PORTAL-TOKEN header. The token is returned on portal creation and webhook payloads — it is not exposed via subsequent reads (Portal.publicize strips it).

Get saved searches for a contact

Get saved searches for a contact
GET/portals/:id/saved-searches/:contact

id (uuid) ID of the portal

contact (uuid) ID of the contact whose saved searches to list. The contact must belong to the portal’s brand; the SQL filters by saved_searches.brand so cross-brand pairings return an empty list.

Example URI

GET /portals/:id/saved-searches/:contact
URI Parameters
HideShow
id
string (required) Example: 996a4087-4141-40f3-94cd-49d6462af666
contact
string (required) Example: c9547e48-062a-4277-a9d0-b23e551c66d9
Response  200
HideShow
Body
{
  "code": "OK",
  "data": [
    {
      "type": "saved_search",
      "id": "aa11c353-8ee3-41db-b0e2-c0f3dc512daa",
      "title": "Portal Search",
      "minimum_price": 200000,
      "maximum_price": null,
      "currency": "USD",
      "minimum_square_meters": null,
      "maximum_square_meters": null,
      "minimum_lot_square_meters": null,
      "maximum_lot_square_meters": null,
      "minimum_bedrooms": null,
      "maximum_bedrooms": null,
      "minimum_bathrooms": null,
      "maximum_bathrooms": null,
      "minimum_year_built": null,
      "maximum_year_built": null,
      "minimum_parking_spaces": null,
      "property_types": null,
      "property_subtypes": null,
      "listing_statuses": null,
      "architectural_styles": null,
      "points": [
        {
          "longitude": -179,
          "latitude": -89,
          "type": "location"
        },
        {
          "longitude": 179,
          "latitude": -89,
          "type": "location"
        },
        {
          "longitude": 179,
          "latitude": 89,
          "type": "location"
        },
        {
          "longitude": -179,
          "latitude": 89,
          "type": "location"
        },
        {
          "longitude": -179,
          "latitude": -89,
          "type": "location"
        }
      ],
      "mls_areas": null,
      "counties": null,
      "subdivisions": null,
      "postal_codes": null,
      "school_districts": null,
      "primary_schools": null,
      "middle_schools": null,
      "elementary_schools": null,
      "senior_high_schools": null,
      "junior_high_schools": null,
      "intermediate_schools": null,
      "high_schools": null,
      "list_agents": null,
      "list_offices": null,
      "selling_agents": null,
      "selling_offices": null,
      "agents": null,
      "offices": null,
      "pool": null,
      "open_house": null,
      "pets": null,
      "number_of_pets_allowed": null,
      "application_fee": null,
      "appliances": null,
      "furnished": null,
      "fenced_yard": null,
      "office_exclusive": null,
      "master_bedroom_in_first_floor": false,
      "minimum_sold_date": null,
      "search": null,
      "created_at": 1778872279.639731,
      "updated_at": 1778872279.639732,
      "deleted_at": null,
      "proposed_title": ", $200K+, Any Beds"
    }
  ],
  "info": {
    "count": 1,
    "total": 0
  }
}

Portal Contact Attributes

Authenticated by the portal’s own token (X-RECHAT-PORTAL-TOKEN), like the saved-search endpoints above.

Add attributes to a contact

Add attributes to a contact
POST/portals/:id/contacts/:contact/attributes

Adds one or more attributes (tag, phone_number, email, etc.) to a contact owned by the portal’s brand. Mirrors POST /contacts/:id/attributes but is scoped to a portal and does not require a bearer token. The request is recorded with no user_id (the caller is the portal, not an agent).

id (uuid) ID of the portal

contact (uuid) ID of the contact. The contact’s brand must match the portal’s brand or the request fails.

attributes (array, required) Attribute objects to add — same shape consumed by POST /contacts/:id/attributes.

Example URI

POST /portals/:id/contacts/:contact/attributes
URI Parameters
HideShow
id
string (required) Example: 996a4087-4141-40f3-94cd-49d6462af666
contact
string (required) Example: c9547e48-062a-4277-a9d0-b23e551c66d9
Request
HideShow
Body
{
  "attributes": [
    {
      "attribute_type": "tag",
      "text": "PortalLead"
    },
    {
      "attribute_type": "phone_number",
      "text": "+15555550123",
      "label": "Mobile"
    }
  ]
}
Response  200
HideShow
Body
{
  "code": "OK",
  "data": [
    {
      "id": "69d67de7-defb-4d88-9ec8-39cfaea7b081",
      "contact": "c9547e48-062a-4277-a9d0-b23e551c66d9",
      "created_at": 1778872279.773458,
      "updated_at": 1778872279.773458,
      "deleted_at": null,
      "label": null,
      "is_primary": false,
      "is_partner": false,
      "index": null,
      "created_by": null,
      "updated_by": null,
      "attribute_type": "tag",
      "text": "PortalLead",
      "date": null,
      "address": null,
      "type": "contact_attribute"
    },
    {
      "id": "bc6fe9ff-c032-46c1-b1ee-92f7a44f7633",
      "contact": "c9547e48-062a-4277-a9d0-b23e551c66d9",
      "created_at": 1778872279.773606,
      "updated_at": 1778872279.773606,
      "deleted_at": null,
      "label": "Mobile",
      "is_primary": false,
      "is_partner": false,
      "index": null,
      "created_by": null,
      "updated_by": null,
      "attribute_type": "phone_number",
      "text": "+15555550123",
      "date": null,
      "address": null,
      "type": "contact_attribute"
    }
  ],
  "info": {
    "count": 2,
    "total": 0
  }
}

Portal Contact Timeline

Authenticated by the portal’s own token (X-RECHAT-PORTAL-TOKEN), like the saved-search endpoints above.

Record a contact activity

Record a contact activity
POST/portals/:id/contacts/:contact/timeline

Records a timeline activity against a contact owned by the portal’s brand. Mirrors POST /leads/:id/timeline but is scoped to a portal and does not require a bearer token.

id (uuid) ID of the portal

contact (uuid) ID of the contact. The contact’s brand must match the portal’s brand or the request fails.

The body is the same shape consumed by the lead timeline endpoint — action, plus optional listing / lead / object / search fields. Payload normalization (object_class/object_sa branching, MLS-number and listing-id resolution) is shared via Activity.preparePayload.

Example URI

POST /portals/:id/contacts/:contact/timeline
URI Parameters
HideShow
id
string (required) Example: 996a4087-4141-40f3-94cd-49d6462af666
contact
string (required) Example: c9547e48-062a-4277-a9d0-b23e551c66d9
Request
HideShow
Body
{
  "action": "ContactLoggedIn",
  "object_class": "contact_lead",
  "object_sa": {}
}
Response  200
HideShow
Body
{
  "code": "OK",
  "data": {
    "id": "4d27c9ea-4540-4443-a512-091a9fce4eec",
    "reference": "c9547e48-062a-4277-a9d0-b23e551c66d9",
    "reference_type": "Contact",
    "created_at": 1778872281.904612,
    "updated_at": 1778872281.904612,
    "deleted_at": null,
    "object": {},
    "action": "ContactLoggedIn",
    "is_visible": true,
    "brand": null,
    "created_by": null,
    "description": null,
    "type": "activity"
  }
}

Generated by aglio on 15 May 2026