Status: Stub — architecture is finalized, REST endpoint not yet live. Pre-launch reference for partner conversations. ETA for the endpoint: ~1 week from 2026-06-02.


Showingly is the showing-coordination layer underneath real estate. We handle the messy multi-party orchestration of getting a buyer in front of a listing — slot picking, listing-agent confirmation, lockbox code delivery, feedback collection — so you don't have to.

If your product touches real estate buyers and you want to offer showing scheduling without building a showings team, this is for you.

The one-line summary

Your service POSTs to one endpoint. We give you back a URL. You point your user at it. We handle the rest.

That's the entire integration model. No SDK, no JavaScript snippet, no platform-specific work. Just an HTTP POST and a redirect.

Who this is for

  • Discovery layers — agent-matching apps, brokerage portals, "find an agent" services. When a buyer matches with an agent in your product, hand the showing-coordination off to us.
  • Video providers — when a viewer hits "Schedule a Showing" inside your player, send them to us. The viewer metadata (watch %, replays) flows through as a warmth signal.
  • Search apps — IDX-powered websites, mobile listing apps, AI-driven property search. Add a showing-scheduling CTA without owning the calendar logic.
  • AI-agent builders — if your AI books showings for users, talk to us about MCP. See MCP integration below.
  • CRMs and brokerage platforms — embed showing actions inside your existing agent workflow.

The flow

┌──────────────────────┐                ┌──────────────────────┐
│   Your service       │                │      Showingly       │
│  (discovers a buyer  │                │                      │
│   wants a showing)   │                │                      │
└──────────┬───────────┘                └──────────┬───────────┘
           │                                        │
           │  1. POST /api/v1/showing-intents       │
           │  { listing_id, buyer, ... }            │
           │ ─────────────────────────────────────▶ │
           │                                        │
           │  2. { intent_id, resume_url,           │
           │       sms_number, expires_at }         │
           │ ◀───────────────────────────────────── │
           │                                        │
           │  3. Redirect buyer → resume_url        │
           │     (or hand them sms_number)          │
           │                                        │
           │                                        │ ◀─── Buyer interacts:
           │                                        │       picks slot, etc.
           │                                        │
           │  4. We webhook your callback_url       │
           │     on state changes                   │
           │ ◀───────────────────────────────────── │
           │                                        │
           │  (state machine drives                 │
           │   listing-agent approval,              │
           │   lockbox delivery,                    │
           │   feedback collection)                 │
           │                                        │
           │  5. Final webhook:                     │
           │     { state: 'complete' }              │
           │ ◀───────────────────────────────────── │

Create a showing intent

POST https://www.showingly.com/api/v1/showing-intents
Authorization: Bearer pk_partner_<your-key>
Content-Type: application/json

{
  "listing_id": "lst_abc123",
  "buyer": {
    "name": "Sarah Park",
    "phone": "+13035551234",
    "email": "sarah@example.com"
  },
  "buyer_agent_id": "agt_xyz789",
  "requested_window": {
    "earliest": "2026-06-08T18:00:00Z",
    "latest":   "2026-06-09T02:00:00Z"
  },
  "source_metadata": {
    "match_id": "tch_match_42"
  },
  "callback_url": "https://your-domain.com/webhooks/showings"
}

Required

  • listing_id — Showingly's listing ID, or { "mls_id": "<id>", "mls": "<mls-name>" } if you only have MLS data

Strongly preferred

  • buyer.phone — verified phone is the strongest identity anchor. Without it, we'll capture it on the resume URL or via SMS first-touch.
  • buyer_agent_id — if your product already knows which agent is representing the buyer

Optional

  • buyer.name, buyer.email
  • requested_window — if your user picked a rough time window. Without it, we ask the buyer.
  • source_metadata — partner-specific context (video watch %, match ID, anything). Indexed for analytics; surfaces to the listing agent as a warmth signal.
  • callback_url — your webhook for state changes. Without it you'd need to poll the GET endpoint.

Response

{
  "intent_id": "si_01HXVZ...",
  "state": "pending_slot_selection",
  "resume_url": "https://www.showingly.com/i/si_01HXVZ...",
  "sms_number": "+17204440000",
  "expires_at": "2026-06-03T18:00:00Z"
}

Three things you can do with the buyer:

  • Redirect to resume_url — they'll see our scheduling UI with the intent loaded and their context preserved
  • Tell them to text sms_number — for mobile contexts or if you'd rather not redirect them
  • Wait for state-change webhooks on callback_url if you registered one

State machine

Every intent passes through one of these states. We webhook your callback_url on every transition.

StateMeaning
pending_buyer_infoWe don't have enough info to proceed (no phone or no name)
pending_slot_selectionSlots have been offered; awaiting buyer pick
pending_listing_agent_approvalSlot picked; awaiting listing-agent confirm (often auto-confirmed)
confirmedLocked in. Calendars updated.
in_progressWithin the showing window. Lockbox code delivered.
completeShowing happened. Feedback collected.
cancelledExplicitly cancelled by buyer or listing agent
expiredAuto-cancelled — no activity for N hours

Webhooks

We POST to your callback_url on every state change. Signed with HMAC-SHA256 in the X-Showingly-Signature header.

POST https://your-domain.com/webhooks/showings
X-Showingly-Signature: t=1717372800,v1=abc123...
Content-Type: application/json

{
  "event": "showing-intent.state-changed",
  "intent_id": "si_01HXVZ...",
  "from_state": "pending_slot_selection",
  "to_state": "pending_listing_agent_approval",
  "at": "2026-06-08T18:42:31Z",
  "intent": { /* full ShowingIntent object */ }
}

Retry with exponential backoff on non-2xx responses. Idempotency keys per event so you can safely accept retries.

Concrete examples

Discovery layer (Tochigami-style)

You match a buyer with an agent. You want Showingly to handle every showing the buyer schedules with that agent from this point on.

// When buyer matches with agent
const intent = await fetch('https://www.showingly.com/api/v1/showing-intents', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${SHOWINGLY_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    listing_id: matchedListing.id,
    buyer: { name: buyer.name, phone: buyer.phone, email: buyer.email },
    buyer_agent_id: agent.showingly_id,
    source_metadata: { match_id: match.id, platform: 'tochigami' },
    callback_url: 'https://tochigami.com/webhooks/showings',
  }),
}).then(r => r.json());

// Hand off to Showingly
window.location.href = intent.resume_url;
// or, if you prefer mobile:
// alert(`Text ${intent.sms_number} to schedule`);

Video player (WellcomeMat-style)

Viewer clicks "Schedule a Showing" inside your player. You want them to schedule without leaving the video page.

player.on('schedule-click', async (event) => {
  const intent = await fetch('https://www.showingly.com/api/v1/showing-intents', {
    method: 'POST',
    headers: { 'Authorization': `Bearer ${SHOWINGLY_API_KEY}` },
    body: JSON.stringify({
      listing_id: event.listing_id,
      source_metadata: {
        watch_percentage: player.completionRatio,
        replay_count: player.replayCount,
        time_on_kitchen_segment: player.segmentDwell('kitchen'),
      },
      callback_url: 'https://your-video-platform.com/webhooks/showings',
    }),
  }).then(r => r.json());

  // Open an iframe modal on top of your player
  showInlineModal(intent.resume_url);
});

The source_metadata payload is high-signal — a viewer who watched 92% and rewound the kitchen twice is a warmer lead than a click from a still photo. We surface that to the listing agent as part of the showing request.

Generic search app

Same pattern. Add a "Schedule a Showing" button. On click, POST and redirect.

MCP integration

If you're building an AI agent that books showings on behalf of users, don't use the REST API. Use our MCP server.

Install:

npx showingly-mcp configure

Adds a server entry to claude_desktop_config.json (or your equivalent). Your agent gets these tools:

  • search_listings(query)
  • get_availability(listing_id, date_range)
  • request_showing(listing_id, buyer, window) — creates an intent
  • get_showing_status(intent_id)
  • cancel_showing(intent_id)

The MCP tools are thin wrappers around the same REST endpoints. The benefit is your agent doesn't need to know about HTTP — it speaks MCP natively.

Get an API key

We're in private beta. Request access and tell us:

  • What you're building
  • What audience you serve (agents, buyers, AI builders)
  • Rough integration volume estimate

We'll respond and walk you through onboarding. Keys come in two flavors:

  • Partner key (pk_partner_*) — full REST access, webhook-eligible, can create intents on behalf of buyers
  • MCP key (mcp_*) — scoped to MCP tools, for AI-agent builders

Questions

Direct: partners@showingly.com