AGENTIC CRM · MCP-FIRST · OPEN API

Build booking and CRM apps.
Without rebuilding operations.

Use FavCRM, an agentic CRM, as the operational backend for service-business apps: bookings, customer records, payments, WhatsApp, campaigns, approval queues, and audit logs exposed through MCP, REST, and the JavaScript SDK.

Create a workspace key
Free tier · OTP signup ~60s · no card Get API Key — 60 seconds
60-SEC QUICKSTART

# 60-second quickstart

tool register_organisation_request   # send OTP to your email

tool register_organisation_verify   # verify → get fav_mcp_* key

Authorization: Bearer fav_mcp_...

https://api.favcrm.io/mcp  # 190+ tools

JAVASCRIPT / TYPESCRIPT SDK

15 namespaces · OTP auth · works in Node.js, Edge, browser

npm install @favcrm/sdk npm
SETUP

Zero to first call in 4 steps.

Same path for humans and AI agents. Free workspace key in 60 seconds, no credit card.

Step 01 — Get an API key

Agentic registration: MCP tool → email OTP → API key. No portal form.

register_organisation_request({
  email: "[email protected]",
  organisationName: "Your Studio",
  industry: "fitness",
  country: "HK"
})

register_organisation_verify({ requestId, code: "123456" })
→ { apiKey: "fav_mcp_…", companyId, loginUrl }

REST fallback: POST /v6/dev/signupPOST /v6/dev/verify. Existing merchant: Settings → MCP Keys.

Step 02 — Connect

Pick one. All three accept the same Bearer token.

  • MCP — Cursor, Claude, Smithery
    https://api.favcrm.io/mcp
  • SDK — Node.js, Edge, browser
    npm i @favcrm/sdk
  • REST — anything else
    https://api.favcrm.io/v6/...

Step 03 — Authenticate

One header shape across every interface.

Authorization: Bearer fav_mcp_xxx

SDK: sdk.setToken('fav_mcp_xxx') — accepts API keys and JWT session tokens.

Step 04 — Smoke test

Verify auth before doing real work. Returns [] on a fresh sandbox — that's success.

curl https://api.favcrm.io/v6/merchant/bookings/services \
  -H "Authorization: Bearer fav_mcp_xxx"

# MCP equivalent
> Use list_services to list bookable services.
USE CASES

Three wedges. One platform.

Start with the pain your client already feels: missed bookings, scattered customer records, unpaid invoices, or WhatsApp follow-up. Each wedge lands in the same AI Manager CRM.

Wedge 01

Booking Storefront

Drop into Cursor or Claude:

"Use @favcrm/sdk to build a booking page. List services from sdk.bookings.listServices(), show available time slots for a selected date, and let users book with sdk.bookings.createBooking()."
import FavCRM from '@favcrm/sdk';

const sdk = new FavCRM({
  baseUrl: 'https://api.favcrm.io',
  companyId: process.env.FAVCRM_COMPANY_ID,
});

const services = await sdk.bookings.listServices();
const slots = await sdk.bookings.getTimeSlots(serviceId, {
  date: '2026-06-01',
});
const booking = await sdk.bookings.createBooking({
  serviceId,
  slotTime: slots[0].startTime,
  participants: 2,
});

Agent workflow

A · Merchant setup

One-time merchant setup. Fully MCP-native — same tool surface as the customer flow.

  1. 01 create_service_category({ name }) — Optional grouping ("Treatments", "Classes").
  2. 02 create_service({ name, durationMinutes, price, capacity, categoryId? }) — Define a bookable service. Add cancellationPolicy / requiresStaff / requiresResource as needed.
  3. 03 set_staff_availability({ memberId, dayOfWeek, startTime, endTime }) — Weekly working hours per staff member. Use date instead of dayOfWeek for one-off changes.
  4. 04 create_resource({ name, type }) + set_resource_availability(...) — (Optional) For room/equipment-bound bookings.

B · Customer flow

Customer-facing storefront. Works via MCP tools, SDK, or raw REST.

  1. 01 list_services — Render service cards with name, price, duration, capacity.
  2. 02 get_service_detail(serviceId) — (Optional) Show prep notes + cancellation policy on the detail page.
  3. 03 get_available_slots(serviceId, { startDate, endDate }) — Render date picker + open times. Returns [] if fully booked.
  4. 04 create_booking({ serviceId, slotTime, participants, customer }) — Confirm booking. Returns booking ID + status.
  5. 05 cancel_booking({ bookingId, reason? }) — Cancel flow. Server checks policy + computes refund eligibility.

Edge cases agents must handle

  • get_available_slots → [] : render "no availability" instead of erroring.
  • create_booking → 409 Conflict : another customer took the slot between fetch and book — refetch slots.
  • cancel_booking → cooldown error includes cancellationPolicy field — surface to user verbatim.
  • Capacity > 1 services : let user pick participants count up to service.capacity.

Wedge 02

Headless CMS / Blog

Drop into Cursor or Claude:

"Fetch blog posts from FavCRM using @favcrm/sdk and render them in my Next.js site. Use sdk.blog.listPosts() for the index and sdk.blog.getPostBySlug() for each post. Render each block in post.blocks."
// Blog index
const posts = await sdk.blog.listPosts({
  status: 'published',
  limit: 10,
});

// Single post with blocks
const post = await sdk.blog.getPostBySlug('my-article');

// Render blocks
post.blocks.forEach(block => {
  if (block.type === 'heading') renderHeading(block.props);
  if (block.type === 'paragraph') renderText(block.props);
  if (block.type === 'image') renderImage(block.props);
});

Agent workflow

A · Merchant setup

Optional content-model setup. Skip if the default post type fits.

  1. 01 create_category({ name, slug? }) — Organize posts ("News", "Tutorials"). Skip if you only need a flat blog.
  2. 02 create_post_type({ key, label }) — Define a custom content type beyond the default `post` (e.g. `case_study`).
  3. 03 create_post_type_field({ postTypeId, key, label, fieldType }) — Add typed custom fields (text, number, image, etc.) to a post type.

B · Customer flow

Author + render flow. Fully MCP-native — no REST fallback needed.

  1. 01 create_post({ type, title, slug?, blocks }) — Create a post with starting blocks. Slug auto-generated from title if omitted.
  2. 02 append_post_block({ postId, type, props }) — Append heading / paragraph / image / button / divider / video / gallery / form blocks.
  3. 03 update_post({ postId, status: "published" }) — Flip from draft to published when ready.
  4. 04 list_posts({ status: "published", categoryId?, limit, offset }) — Storefront index page.
  5. 05 get_post({ slug }) — Storefront single-page view. Returns post + ordered blocks array.

Edge cases agents must handle

  • Block shape: id, version, type, data — id is a unique block UUID, version is an integer, data is the block-specific payload.
  • Block types: paragraph, heading, image, list, quote, code, divider, embed, file, faq, callout, gallery, cta, accordion, product.
  • Slug collision → 409 Conflict. Either auto-suffix client-side or omit slug to let server generate.
  • append_post_block reorder: use `reorder_post_blocks` for full reorder, or `replace_post_block(index)` for in-place edits.
  • Draft posts (status: "draft") are not returned by list_posts unless authed as the author.

Wedge 03

Run bookings, campaigns, and commerce together

Drop into Cursor or Claude:

"Use FavCRM MCP to run my whole business: list_bookings for today, list_orders for pending fulfilment, create_campaign + create_promotion to launch a flash sale to VIP members. My MCP key is fav_mcp_..."
// One platform — bookings + shop + campaigns + promos
const [bookings, products, campaigns] = await Promise.all([
  sdk.bookings.list({ status: 'confirmed' }),
  sdk.shop.listProducts({ inStock: true }),
  sdk.campaigns.list({ status: 'active' }),
]);

// Launch a flash sale to a VIP segment
const promo = await sdk.promotions.create({
  name: 'VIP Flash 20%', code: 'VIP20',
  type: 'percentage', value: '20',
  endsAt: '2026-06-30T23:59:00Z', onlineEnabled: true,
});

const campaign = await sdk.campaigns.create({
  name: 'VIP Flash Sale',
  channel: 'email',
  recipientSource: 'segment',
  segmentId: 'vip-segment-id',
  channelConfig: { subject: '20% off this weekend', html: '...' },
});

Agent workflow

A · Merchant setup

Provision the catalog + audience once. Fully MCP-native.

  1. 01 create_product_category({ name }) + create_product({ name, price, ... }) — Build the shop catalog. Use list_product_categories first if you want to attach to existing groups.
  2. 02 list_customer_segments + create_customer_segment(...) — Define audience segments (VIP, recent buyers, lapsed) for campaign targeting.
  3. 03 create_promotion({ name, code, type, value, ...channelFlags }) — Create promo / coupon codes. Toggle bookingEnabled / onlineEnabled / posEnabled to scope.
  4. 04 create_service + set_staff_availability — See Wedge 01 for booking-side setup.

B · Customer flow

Daily ops + marketing automation. All MCP-native today (campaign send still REST — see edge cases).

  1. 01 list_bookings({ status: "confirmed", date }) + list_orders({ status: "pending" }) — Daily dashboard / fulfilment queue.
  2. 02 create_shop_order({ accountId, items, promotionCode? }) — Create orders programmatically (e.g. from a chat agent or quote-to-order flow).
  3. 03 validate_promotion({ promotionCode, channel, amount }) — Pre-check coupon at checkout — returns isValid + discountAmount.
  4. 04 create_campaign({ name, channel, recipientSource: "segment", segmentId, channelConfig }) — Stage an email/SMS/WhatsApp campaign in DRAFT.
  5. 05 POST /v6/merchant/campaigns/{id}/send — Trigger send (REST only — MCP send tool needs queue binding, coming next).

Edge cases agents must handle

  • send_campaign requires NOTIFICATIONS queue access — currently REST-only (POST /v6/merchant/campaigns/:id/send). MCP tool tracked in claudedocs/mcp-tools-gap.md.
  • create_promotion: code is uppercased server-side. Collisions return a unique-constraint error — surface as "code already used".
  • validate_promotion: amount is in major units (dollars, not cents). Returns errorCode: PROMOTION_NOT_FOUND / EXPIRED / USAGE_LIMIT_REACHED / etc.
  • create_campaign: status defaults to DRAFT. SCHEDULED requires a future scheduledAt. Cannot delete after status=SENT.
  • list_orders + create_shop_order respect the company's active currency — multi-currency mixed orders not supported in v1.

Ready to build?

Register through MCP in 60 seconds. No portal form. Email OTP, then a fresh fav_mcp_* key for a Free workspace. Upgrade to Starter at US$49 when the client is ready for production.