Brick & Yield

Brick & Yield API

The Brick & Yield API lets you sync clients, notes, tags, and tasks between Brick & Yield and your CRM or other tools. It powers the official Brick & Yield Zapier integration, and can be used directly by any HTTP client.

Base URL
https://api.brickandyield.app
Contents
  1. Overview
  2. Authentication
  3. Conventions & errors
  4. How clients are matched
  5. Connection test
  6. Clients
  7. Notes, tags & tasks
  8. Webhooks (triggers)
  9. Webhook event payloads
  10. Field reference

Overview

The API is organized around REST. All requests and responses use JSON. Every endpoint is scoped to a single agent — an API key can only read and write that agent's own clients and their related records. There is no access to other agents' data.

The API is versioned under /api/v1. Two-way sync is supported: you can push data in with the actions below, and receive real-time events out via webhooks (see Webhooks).

Authentication

The API uses per-agent API keys. An agent generates a key in the Brick & Yield admin app under Settings → API Keys. The key is shown once at creation time and stored hashed — if it is lost, revoke it and generate a new one.

Pass the key as a bearer token on every request. X-API-Key: <key> is also accepted.

Authorization: Bearer by_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Requests without a valid, non-revoked key return 401 Unauthorized. Verify a key with the connection test endpoint.

Conventions & errors

Successful responses include "ok": true alongside the returned resource. Write endpoints return 201 Created; reads and idempotent updates return 200 OK.

Errors return a non-2xx status with a JSON body:

{ "error": "Client not found." }
FieldTypeDescription
400Bad RequestMissing or invalid fields (body includes validation details).
401UnauthorizedMissing, invalid, or revoked API key.
404Not FoundThe referenced client does not exist for this agent.
500Server ErrorUnexpected error; safe to retry.

How clients are matched

Create/update and find operations locate an existing client using the following identifiers, in order. The first one that matches wins — this keeps repeated syncs from creating duplicates:

  1. CRM Record IDexternal_id (exact match). Recommended: store your CRM's contact ID so matching survives email changes.
  2. Email — case-insensitive exact match.
  3. Phone — normalized to the last 10 digits.

Note, tag, and task endpoints accept any of these in the {id} path segment — the Brick & Yield client UUID, the external_id, or the client's email.

Connection test

Returns the agent and organization the API key belongs to. Used to verify a key.

GET/api/v1/me

Example

curl https://api.brickandyield.app/api/v1/me \
  -H "Authorization: Bearer by_live_xxx"

Response 200

{
  "ok": true,
  "agent":        { "id": "…", "name": "Jane Agent", "email": "jane@brokerage.com" },
  "organization": { "id": "…", "name": "Acme Realty" }
}

Clients

POST/api/v1/clients

Create a client, or update the existing one if a match is found (see matching). On update, only the fields you send are changed; omitted fields are left as-is. New clients are created without an app login (the agent can invite them to the client portal later).

Body

FieldTypeDescription
external_idstringYour CRM's contact ID. Strongly recommended for reliable matching.
external_sourcestringCRM name, e.g. "hubspot", "salesforce".
first_namestringGiven name.
last_namestringFamily name.
full_namestringFull name. Derived from first/last if omitted.
emailstringEmail address.
phonestringPhone number (any format).
stageenumBuyer stage — see Field reference.
portal_typeenumbuyer · seller · both.
client_typeenumSee Field reference.
tagsstring[] | stringTag names to add (array or comma-separated). Additive — never removes tags.

At least one of full_name, first_name/last_name, email, or phone is required.

Example

curl -X POST https://api.brickandyield.app/api/v1/clients \
  -H "Authorization: Bearer by_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "external_id": "crm-123",
    "external_source": "hubspot",
    "first_name": "Jane",
    "last_name": "Doe",
    "email": "jane@example.com",
    "phone": "(801) 555-1234",
    "stage": "new",
    "portal_type": "buyer",
    "tags": ["Hot Lead", "Investor"]
  }'

Response 201 (created) / 200 (updated)

{
  "ok": true,
  "created": true,
  "client": {
    "id": "541218ce-9b41-4c1a-ba01-65b2d15a2a09",
    "external_id": "crm-123",
    "external_source": "hubspot",
    "first_name": "Jane",
    "last_name": "Doe",
    "full_name": "Jane Doe",
    "email": "jane@example.com",
    "phone": "(801) 555-1234",
    "stage": "new",
    "portal_type": "buyer",
    "client_type": "home_buyer",
    "source": "zapier",
    "created_at": "2026-01-01T00:00:00.000Z",
    "updated_at": "2026-01-01T00:00:00.000Z"
  }
}
GET/api/v1/clients

Find a single client by external_id, email, or phone (query parameters). At least one is required. Returns "client": null when nothing matches.

Example

curl "https://api.brickandyield.app/api/v1/clients?email=jane@example.com" \
  -H "Authorization: Bearer by_live_xxx"

Response 200

{ "ok": true, "client": { "id": "…", "full_name": "Jane Doe", … } }

Notes, tags & tasks

For each of these, {id} may be the Brick & Yield client UUID, the external_id, or the client's email (URL-encode it).

POST/api/v1/clients/{id}/notes

Body

FieldTypeDescription
bodystringNote text (required, up to 5000 chars).

Example

curl -X POST https://api.brickandyield.app/api/v1/clients/crm-123/notes \
  -H "Authorization: Bearer by_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{ "body": "Called, left a voicemail." }'

Response 201

{ "ok": true, "note": { "id": "…", "body": "Called, left a voicemail.", "created_at": "…", "source": "zapier" } }
POST/api/v1/clients/{id}/tags

Adds a tag, creating the org-level tag if it doesn't exist yet. Additive.

Body

FieldTypeDescription
namestringTag name (required).
colorstringOptional hex color, e.g. "#10b981".

Response 201

{ "ok": true, "tag": { "id": "…", "name": "Hot Lead", "color": "#10b981" } }
POST/api/v1/clients/{id}/tasks

Body

FieldTypeDescription
titlestringTask title (required).
descriptionstringOptional details.
due_datestringOptional, YYYY-MM-DD.

Example

curl -X POST https://api.brickandyield.app/api/v1/clients/crm-123/tasks \
  -H "Authorization: Bearer by_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{ "title": "Send listing agreement", "description": "Get it signed by Friday.", "due_date": "2026-01-05" }'

Response 201

{ "ok": true, "task": { "id": "…", "title": "Send listing agreement", "description": "Get it signed by Friday.", "due_date": "2026-01-05", "completed": false, "source": "zapier" } }

Webhooks (triggers)

The API delivers real-time events via REST hooks. You subscribe a target URL to an event type; Brick & Yield then POSTs the event payload to that URL whenever it occurs. Events fire only from in-app activity, never from API writes — so a two-way sync will not loop.

POST/api/v1/hooks/subscribe

Body

FieldTypeDescription
eventenumOne of the event types below.
target_urlstringHTTPS URL that will receive the POSTed event.

Example

curl -X POST https://api.brickandyield.app/api/v1/hooks/subscribe \
  -H "Authorization: Bearer by_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{ "event": "client.updated", "target_url": "https://hooks.example.com/abc" }'

Response 201

{ "ok": true, "id": "5b3d483d-…" }
DELETE/api/v1/hooks/subscribe/{id}

Removes a subscription by the id returned from subscribe.

{ "ok": true }
GET/api/v1/hooks/sample

Returns up to 3 recent items shaped exactly like the live webhook payload, for building and testing a subscription. Pass ?event= with one of the event types.

curl "https://api.brickandyield.app/api/v1/hooks/sample?event=client.updated" \
  -H "Authorization: Bearer by_live_xxx"

Event types

FieldTypeDescription
client.createdeventA client was created in Brick & Yield.
client.updatedeventA client was created or edited — fields, stage, or tags.
client.stage_changedeventA client's stage changed.
note.createdeventA note was added to a client.
task.createdeventA task was created for a client.
tag.addedeventA tag was added to a client.

Webhook event payloads

Each event is delivered as a JSON POST body. The shapes are:

client.created · client.updated · client.stage_changed

{
  "event": "client.updated",
  "client": {
    "id": "541218ce-9b41-4c1a-ba01-65b2d15a2a09",
    "external_id": "crm-123",
    "external_source": "hubspot",
    "first_name": "Jane",
    "last_name": "Doe",
    "full_name": "Jane Doe",
    "email": "jane@example.com",
    "phone": "(801) 555-1234",
    "stage": "new",
    "portal_type": "buyer",
    "client_type": "home_buyer",
    "tags": ["Hot Lead", "Investor"]
  }
}

note.created

{
  "event": "note.created",
  "note":   { "id": "…", "body": "Called, left a voicemail.", "created_at": "…" },
  "client": { "id": "…", "full_name": "Jane Doe", "external_id": "crm-123", "email": "jane@example.com" }
}

task.created

{
  "event": "task.created",
  "task":   { "id": "…", "title": "Send listing agreement", "description": "…", "due_date": "2026-01-05", "completed": false },
  "client": { "id": "…", "full_name": "Jane Doe", "external_id": "crm-123", "email": "jane@example.com" }
}

tag.added

{
  "event": "tag.added",
  "tag":    { "id": "…", "name": "Hot Lead", "color": "#10b981" },
  "client": { "id": "…", "full_name": "Jane Doe", "external_id": "crm-123", "email": "jane@example.com" }
}

Field reference

Buyer stage (stage)

new · active · nurture · touring · under_contract · closed · paused

Portal type (portal_type)

buyer · seller · both

Client type (client_type)

investor · out_of_state_investor · house_hacker · home_buyer · seller_only

Sign in to Brick & Yield