API Reference
Complete reference for all Blendo API v1 endpoints. For a compact table of every endpoint, see the quick-reference table.
Authentication
All API v1 requests require a Bearer token. Generate an API key in Settings → API Key or via the API Keys endpoints.
Include the key in every request as an Authorization header:
Authorization: Bearer optk_your_api_key_here API keys are scoped to your account. All resources returned are limited to those owned by your account.
Scopes
When creating an API key, you can assign scopes to limit what the key can do:
| Scope | Access |
|---|---|
read | GET requests only |
write | POST, PATCH, DELETE requests |
| (no scopes) | Full access (read + write) |
Rate Limiting
API requests are rate-limited to 60 requests per minute per IP address. If you exceed this limit, you'll receive a 429 Too Many Requests response.
Base URL
https://my.blendo.com/api/v1 All endpoint paths below are relative to this base URL.
Response Format
Single Resource
All successful responses wrap data in a data key:
{
"data": {
"id": "01HQ...",
"name": "My Site",
"slug": "my-site",
"created_at": "2026-04-01T12:00:00Z"
}
} Paginated Lists
List endpoints return paginated results with a meta object:
{
"data": [ ... ],
"meta": {
"current_page": 1,
"per_page": 25,
"total": 48,
"last_page": 2
}
} Control pagination with query parameters:
| Parameter | Default | Description |
|---|---|---|
page | 1 | Page number |
per_page | 25 | Items per page (max 100) |
Errors
Error responses include an error key with a human-readable message:
// 404 Not Found
{
"error": "Not found"
}
// 422 Validation Error
{
"message": "The name field is required.",
"errors": {
"name": ["The name field is required."]
}
}
// 429 Rate Limited
{
"error": "Too many requests."
} Delete Responses
Successful deletes return:
{
"data": {
"deleted": true
}
} Sites
Sites are the top-level container for pages, posts, forms, and settings. Each site gets a subdomain at slug.blendo.com or a custom domain.
GET /sites
List all sites in your account.
curl https://my.blendo.com/api/v1/sites \
-H "Authorization: Bearer optk_your_key" Response: Paginated list with fields: id, name, slug, site_type, custom_domain, tagline, is_published, created_at, updated_at.
POST /sites
Create a new site.
curl -X POST https://my.blendo.com/api/v1/sites \
-H "Authorization: Bearer optk_your_key" \
-H "Content-Type: application/json" \
-d '{
"name": "My Portfolio",
"slug": "my-portfolio",
"site_type": "portfolio",
"tagline": "Design work by Jane"
}' | Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Display name (max 255) |
slug | string | Yes | Subdomain slug (lowercase, alphanumeric + hyphens) |
site_type | string | No | brochure, portfolio, blog, or shop. Default: brochure |
tagline | string | No | Short description (max 500) |
Response (201):
{
"data": {
"id": "01J5ABC...",
"name": "My Portfolio",
"slug": "my-portfolio",
"site_type": "portfolio",
"created_at": "2026-04-06T10:00:00Z"
}
} GET /sites/{id}
Get a single site with full details including page/post counts, branding, navigation links, and social links.
PATCH /sites/{id}
Update a site. Send only the fields you want to change.
| Field | Type | Description |
|---|---|---|
name | string | Display name |
slug | string | Subdomain slug |
tagline | string | Short description |
site_type | string | brochure, portfolio, blog, shop |
favicon_url | string | URL to favicon image |
og_image_url | string | Default Open Graph image |
logo_url | string | Logo image URL |
logo_text | string | Text-based logo |
meta_title_suffix | string | Appended to all page titles (e.g. | My Brand) |
google_analytics_id | string | GA measurement ID (G-XXXXXX) |
nav_links | array | Array of {label, url, external} |
social_links | array | Array of {platform, url} |
timezone | string | IANA timezone (e.g. America/Chicago) |
language | string | Language code (e.g. en) |
is_published | boolean | Toggle site visibility |
brand_id | string | Associate a brand guideline set |
DELETE /sites/{id}
Delete a site and all its pages. This action is irreversible.
curl -X DELETE https://my.blendo.com/api/v1/sites/01J5ABC... \
-H "Authorization: Bearer optk_your_key" Pages
Pages contain HTML content, SEO metadata, and version history. Pages belong to a site.
GET /pages
List all pages across your account. Returns: id, title, slug, pathway, status, published_at, created_at, updated_at.
curl https://my.blendo.com/api/v1/pages \
-H "Authorization: Bearer optk_your_key" GET /pages/{id}
Get a single page with full content, SEO data, and status.
curl https://my.blendo.com/api/v1/pages/01J5ABC... \
-H "Authorization: Bearer optk_your_key" Response:
{
"page": {
"id": "01J5ABC...",
"title": "Launch Event",
"slug": "launch-event",
"pathway": "event",
"status": "published",
"content": {
"html": "<style>...</style><section>...</section>",
"google_fonts": "Inter:400,700",
"title": "Launch Event",
"meta_description": "Join us for..."
},
"seo": {
"meta_title": "Launch Event",
"meta_description": "Join us for..."
},
"published_at": "2026-04-01T12:00:00Z",
"created_at": "2026-04-01T11:00:00Z",
"updated_at": "2026-04-01T12:00:00Z"
}
} PATCH /pages/{id}
Update a page. Creates a version snapshot before saving content changes.
| Field | Type | Description |
|---|---|---|
title | string | Page title |
content | object | Page content (html, google_fonts, meta_description) |
block_tree | array | Block-format content (alternative to html content) |
seo | object | SEO metadata (meta_title, meta_description) |
POST /pages/{id}/publish
Publish a page. Renders the HTML and deploys it to the edge CDN.
curl -X POST https://my.blendo.com/api/v1/pages/01J5ABC.../publish \
-H "Authorization: Bearer optk_your_key" POST /pages/{id}/unpublish
Unpublish a page. Removes it from the edge CDN and sets status to draft.
GET /pages/{id}/versions
List all saved versions of a page, ordered by version number descending.
{
"versions": [
{
"id": "01J5XYZ...",
"version": 3,
"change_summary": "API update",
"created_at": "2026-04-05T14:30:00Z"
}
]
} Posts
Blog posts with markdown content, tags, and author information. Posts belong to a site.
GET /sites/{site_id}/posts
List posts for a site. Filter by ?status=published or ?status=draft.
curl https://my.blendo.com/api/v1/sites/01J5ABC.../posts \
-H "Authorization: Bearer optk_your_key" POST /sites/{site_id}/posts
Create a new post on a site.
curl -X POST https://my.blendo.com/api/v1/sites/01J5ABC.../posts \
-H "Authorization: Bearer optk_your_key" \
-H "Content-Type: application/json" \
-d '{
"title": "Getting Started with Blendo",
"body": "# Welcome\n\nThis is your first post...",
"tags": ["tutorial", "getting-started"],
"status": "draft"
}' | Field | Type | Required | Description |
|---|---|---|---|
title | string | Yes | Post title (max 255) |
body | string | Yes | Markdown content |
slug | string | No | URL slug (auto-generated from title if omitted) |
excerpt | string | No | Short summary (max 1000) |
tags | array | No | Array of tag strings |
author | string | No | Author name (defaults to your name) |
featured_image | string | No | Image URL |
status | string | No | draft or published. Default: draft |
GET /posts/{id}
Get a single post with full body content.
PATCH /posts/{id}
Update a post. Send only the fields you want to change. Same fields as create.
DELETE /posts/{id}
Permanently delete a post.
POST /posts/{id}/publish
Set the post status to published and set published_at if not already set.
Media
Upload and manage images via a presigned URL flow. Images are stored on Cloudflare R2 and served from the CDN at cdn.blendo.site.
GET /media
List media items in your account. Returns: id, filename, cdn_url, mime_type, file_size, width, height, alt_text, tags, created_at.
GET /media/{id}
Get a single media item with full metadata including license and attribution info.
POST /media/presign
Request a presigned upload URL. Upload your file directly to R2 using the returned URL, then confirm the upload.
curl -X POST https://my.blendo.com/api/v1/media/presign \
-H "Authorization: Bearer optk_your_key" \
-H "Content-Type: application/json" \
-d '{
"filename": "hero-banner.jpg",
"mime_type": "image/jpeg",
"file_size": 245000
}' | Field | Type | Required | Description |
|---|---|---|---|
filename | string | Yes | Original filename |
mime_type | string | Yes | image/jpeg, image/png, image/gif, image/webp, image/svg+xml |
file_size | integer | Yes | File size in bytes (max 10 MB) |
Response: Returns upload_url (PUT to this URL with the raw file) and r2_key.
POST /media/confirm
Confirm an upload after putting the file to the presigned URL. This creates the media item record.
| Field | Type | Required | Description |
|---|---|---|---|
r2_key | string | Yes | The key from the presign response |
filename | string | Yes | Original filename |
mime_type | string | Yes | MIME type |
file_size | integer | Yes | File size in bytes |
width | integer | No | Image width in pixels |
height | integer | No | Image height in pixels |
alt_text | string | No | Alt text for accessibility |
PATCH /media/{id}
Update media metadata (alt text and tags only).
DELETE /media/{id}
Delete a media item and remove it from storage.
Forms
Create and manage forms with custom fields. Forms collect submissions and can trigger email notifications.
GET /forms
List all forms with submission counts.
GET /forms/{id}
Get a form with its field definitions, settings, and unread submission count.
POST /forms
Create a new form.
curl -X POST https://my.blendo.com/api/v1/forms \
-H "Authorization: Bearer optk_your_key" \
-H "Content-Type: application/json" \
-d '{
"site_id": "01J5ABC...",
"name": "Contact Form",
"type": "contact",
"fields": [
{"key": "name", "label": "Name", "type": "text", "required": true},
{"key": "email", "label": "Email", "type": "email", "required": true},
{"key": "message", "label": "Message", "type": "textarea", "required": true}
]
}' | Field | Type | Required | Description |
|---|---|---|---|
site_id | string | Yes | The site this form belongs to |
name | string | Yes | Form name (max 255) |
type | string | Yes | contact, subscribe, register, or custom |
fields | array | Yes | Array of field definitions (key, label, type, required) |
settings | object | No | Form settings (notification email, redirect URL, etc.) |
Supported field types: text, email, textarea, select, radio, checkbox, phone, url, number, date, time, hidden, html_block, section_break, page_break, multi_select, name, consent.
PATCH /forms/{id}
Update a form's name, fields, settings, or active status.
DELETE /forms/{id}
Delete a form and all its submissions.
GET /forms/{id}/submissions
List submissions for a specific form (excluding spam). Paginated.
curl https://my.blendo.com/api/v1/forms/01J5ABC.../submissions \
-H "Authorization: Bearer optk_your_key" Submissions & Subscribers (Legacy)
These endpoints return submissions and subscribers across all your pages. For form-specific submissions, use the Forms endpoints instead.
GET /submissions
List form submissions across all pages. Filter with ?page_id=... and ?action=....
GET /subscribers
List email subscribers across all sites.
Brands
Brand guidelines define your visual identity: colors, typography, buttons, inputs, and layout rules. Brands are account-level and can be attached to one or more sites.
GET /brands
List all brands in your account.
GET /brands/{id}
Get a brand with full guidelines and connected site count.
POST /brands
Create a brand.
curl -X POST https://my.blendo.com/api/v1/brands \
-H "Authorization: Bearer optk_your_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Acme Corp",
"guidelines": {
"colors": {"primary": "#EF233C", "secondary": "#2563EB", "background": "#FFFFFF"},
"typography": {"heading": "Space Grotesk", "body": "Inter"},
"buttons": {"radius": "8px", "style": "filled"},
"inputs": {"radius": "6px", "border": "1px solid #E2E8F0"},
"layout": {"max_width": "1200px", "spacing": "relaxed"}
}
}' | Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Brand name (max 100) |
logo_url | string | No | Logo image URL |
guidelines | object | Yes | Contains: colors, typography, buttons, inputs, layout |
PATCH /brands/{id}
Update a brand's name, logo, or guidelines.
DELETE /brands/{id}
Delete a brand. Sites using this brand will be unlinked. If the deleted brand was the default, the next brand becomes default.
Templates
Browse and use pre-built page templates. Templates are read-only; you can use them to create new pages.
GET /templates
List available templates. Returns: id, title, slug, pathway, purpose, description, style_family, features, is_featured, use_count, thumbnail_path.
POST /templates/{slug}/use
Create a new draft page from a template. If you don't have a site yet, one is created automatically.
curl -X POST https://my.blendo.com/api/v1/templates/community-garden/use \
-H "Authorization: Bearer optk_your_key" Response (201):
{
"data": {
"page_id": "01J5XYZ...",
"site_id": "01J5ABC...",
"title": "Community Garden",
"slug": "community-garden",
"status": "draft"
}
} Menus
Navigation menus for site headers, footers, and mobile navigation.
GET /sites/{site_id}/menus
List all menus for a site.
POST /sites/{site_id}/menus
Create a menu. Only one menu per location is allowed.
curl -X POST https://my.blendo.com/api/v1/sites/01J5ABC.../menus \
-H "Authorization: Bearer optk_your_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Main Navigation",
"location": "header",
"items": [
{"label": "Home", "url": "/"},
{"label": "About", "url": "/about/"},
{"label": "Blog", "url": "/blog/"}
]
}' | Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Menu name (max 100) |
location | string | Yes | header, footer, mobile, or sidebar |
items | array | No | Array of menu items with label and url |
PATCH /menus/{id}
Update a menu's name or items.
DELETE /menus/{id}
Delete a menu.
Redirects
Manage URL redirects for your site. Useful for preserving SEO when restructuring pages.
GET /sites/{site_id}/redirects
List redirects for a site. Filter by ?search= to match source or target URLs.
POST /sites/{site_id}/redirects
Create a redirect rule.
curl -X POST https://my.blendo.com/api/v1/sites/01J5ABC.../redirects \
-H "Authorization: Bearer optk_your_key" \
-H "Content-Type: application/json" \
-d '{
"source_path": "/old-page/",
"target_url": "/new-page/",
"status_code": 301
}' | Field | Type | Required | Description |
|---|---|---|---|
source_path | string | Yes | Path to redirect from (must start with /) |
target_url | string | Yes | Destination URL or path |
status_code | integer | No | 301 (permanent) or 302 (temporary). Default: 301 |
PATCH /redirects/{id}
Update a redirect's source, target, status code, or active state.
DELETE /redirects/{id}
Delete a redirect.
Webhooks
Receive real-time notifications when events happen on your site. Webhooks are signed with a secret for verification.
GET /webhooks
List all webhooks. Filter by ?site_id=....
POST /webhooks
Create a webhook endpoint.
curl -X POST https://my.blendo.com/api/v1/webhooks \
-H "Authorization: Bearer optk_your_key" \
-H "Content-Type: application/json" \
-d '{
"site_id": "01J5ABC...",
"url": "https://example.com/webhooks/blendo",
"events": ["site.updated", "post.created", "form.submitted"],
"description": "Sync to CRM"
}' Response (201): Includes a secret field (starts with whsec_) that is only shown at creation time. Use it to verify webhook signatures.
PATCH /webhooks/{id}
Update a webhook's URL, events, headers, description, or active state.
DELETE /webhooks/{id}
Delete a webhook.
Analytics
Query aggregated analytics data: pageviews, CTA clicks, unique visitors, referrers, and per-page breakdown.
GET /analytics
Get account-wide analytics.
curl "https://my.blendo.com/api/v1/analytics?date_from=2026-03-01&date_to=2026-03-31&granularity=day" \
-H "Authorization: Bearer optk_your_key" | Parameter | Default | Description |
|---|---|---|
date_from | 7 days ago | Start date (YYYY-MM-DD) |
date_to | Today | End date (YYYY-MM-DD) |
granularity | day | day or hour |
Response:
{
"data": {
"totals": {
"pageviews": 12540,
"cta_clicks": 834,
"unique_visitors": 8320
},
"time_series": [
{"period": "2026-03-01", "pageviews": 420, "cta_clicks": 28, "unique_visitors": 280}
],
"top_referrers": {
"google.com": 3200,
"twitter.com": 890,
"direct": 4230
},
"top_pages": [
{"page_id": "01J5...", "title": "Home", "slug": "home", "pageviews": 5400, "cta_clicks": 312}
]
}
} GET /analytics/pages/{page_id}
Get analytics for a specific page. Same parameters and response structure as above, plus top_ctas (most-clicked buttons).
Experiments (A/B Testing)
Create and manage A/B test experiments on your pages.
GET /experiments
List all experiments with their page info and variants.
GET /experiments/{id}
Get a single experiment with variants and winner info.
POST /experiments
Create a new experiment. A "Control" variant is automatically created from the page's current content.
curl -X POST https://my.blendo.com/api/v1/experiments \
-H "Authorization: Bearer optk_your_key" \
-H "Content-Type: application/json" \
-d '{
"page_id": "01J5ABC...",
"name": "Hero CTA Test",
"goal": "cta_click",
"traffic_pct": 50
}' | Field | Type | Required | Description |
|---|---|---|---|
page_id | string | Yes | Page to run the experiment on |
name | string | Yes | Experiment name (max 255) |
goal | string | Yes | cta_click or form_submit |
traffic_pct | integer | Yes | Percentage of traffic included (10-100) |
POST /experiments/{id}/start
Start running the experiment. Requires at least 2 variants.
POST /experiments/{id}/stop
Pause the experiment.
POST /experiments/{id}/complete
Complete the experiment and apply the winning variant's content to the page.
curl -X POST https://my.blendo.com/api/v1/experiments/01J5.../complete \
-H "Authorization: Bearer optk_your_key" \
-H "Content-Type: application/json" \
-d '{"winner_variant_id": "01J5XYZ..."}' Newsletters
Create, schedule, and send newsletters to your subscribers.
GET /newsletters
List newsletters. Filter by ?status=draft, ?status=sent, or ?status=scheduled.
GET /newsletters/{id}
Get a newsletter with segment information.
POST /newsletters
Create a newsletter.
curl -X POST https://my.blendo.com/api/v1/newsletters \
-H "Authorization: Bearer optk_your_key" \
-H "Content-Type: application/json" \
-d '{
"title": "March Update",
"body": "# March Update\n\nHere is what happened this month...",
"excerpt": "A quick recap of March.",
"tags": ["monthly", "update"]
}' | Field | Type | Required | Description |
|---|---|---|---|
title | string | Yes | Newsletter title |
body | string | Yes | Markdown content |
excerpt | string | No | Short summary (max 500) |
featured_image | string | No | Header image URL |
author | string | No | Author name |
tags | array | No | Tag array |
segment_id | string | No | Send only to this subscriber segment |
is_premium | boolean | No | Mark as premium/paid content |
PATCH /newsletters/{id}
Update a draft newsletter. Cannot edit sent newsletters.
POST /newsletters/{id}/send
Send the newsletter immediately to all matching subscribers.
POST /newsletters/{id}/schedule
Schedule the newsletter for later delivery.
curl -X POST https://my.blendo.com/api/v1/newsletters/01J5.../schedule \
-H "Authorization: Bearer optk_your_key" \
-H "Content-Type: application/json" \
-d '{"scheduled_at": "2026-04-10T09:00:00Z"}' Invoices
Create and manage invoices for customers.
GET /invoices
List invoices. Filter by ?status=unpaid, ?status=overdue, ?status=paid, ?status=draft, ?status=void.
GET /invoices/{id}
Get a single invoice with customer, line items, booking, and receipt details.
POST /invoices
Create an invoice with line items.
curl -X POST https://my.blendo.com/api/v1/invoices \
-H "Authorization: Bearer optk_your_key" \
-H "Content-Type: application/json" \
-d '{
"site_id": "01J5ABC...",
"customer_id": "01J5CUS...",
"due_date": "2026-04-20",
"items": [
{"description": "Website design", "quantity": 1, "unit_price": 250000},
{"description": "Hosting (annual)", "quantity": 1, "unit_price": 34800}
]
}' unit_price: 250000 = $2,500.00. All monetary values in the API use the smallest currency unit.
POST /invoices/{id}/send
Send the invoice to the customer via email. Requires at least one line item.
POST /invoices/{id}/mark-paid
Mark an invoice as paid. Optionally specify payment method: ?payment_method=cash (default), stripe, or comp.
POST /invoices/{id}/void
Void an invoice (irreversible).
Membership Plans
Define membership tiers for your site (subscription, punch-card packs, or time-limited passes).
GET /membership-plans
List all plans with active/total member counts.
POST /membership-plans
Create a membership plan.
| Field | Type | Required | Description |
|---|---|---|---|
site_id | string | Yes | Site ID |
name | string | Yes | Plan name |
type | string | Yes | subscription, pack, or pass |
price | integer | Yes | Price in cents |
billing_interval | string | No | month or year (for subscriptions) |
trial_days | integer | No | Free trial duration |
credit_amount | integer | No | Number of credits (for packs) |
valid_days | integer | No | Expiration in days (for passes) |
access_level | string | No | basic, premium, or vip |
features | array | No | Array of feature description strings |
PATCH /membership-plans/{id}
Update a plan's name, price, features, or active status.
DELETE /membership-plans/{id}
Delete a plan. Fails if there are active members on it.
Memberships
Enroll customers in membership plans and manage their lifecycle.
GET /memberships
List all memberships with plan and customer details. Filter by ?status=active, ?status=paused, ?status=cancelled.
POST /memberships
Enroll a customer in a plan.
curl -X POST https://my.blendo.com/api/v1/memberships \
-H "Authorization: Bearer optk_your_key" \
-H "Content-Type: application/json" \
-d '{
"plan_id": "01J5PLN...",
"customer_id": "01J5CUS...",
"payment_method": "stripe"
}' POST /memberships/{id}/pause
Pause a membership (preserves remaining credits/time).
POST /memberships/{id}/resume
Resume a paused membership.
POST /memberships/{id}/cancel
Cancel a membership.
Events
Create and manage events with ticket tiers, venues, and check-in.
GET /events
List events. Filter by ?status=draft, ?status=published, ?status=cancelled, ?status=completed.
GET /events/{id}
Get an event with venue, ticket tiers, sessions, and ticket statistics (total, valid, used, cancelled, revenue, check-in rate).
POST /events
Create an event.
curl -X POST https://my.blendo.com/api/v1/events \
-H "Authorization: Bearer optk_your_key" \
-H "Content-Type: application/json" \
-d '{
"site_id": "01J5ABC...",
"name": "Summer Gala",
"event_type": "single",
"start_at": "2026-07-15T18:00:00Z",
"end_at": "2026-07-15T23:00:00Z",
"capacity": 200,
"tiers": [
{"name": "General Admission", "price": 5000, "quantity_available": 150},
{"name": "VIP", "price": 15000, "quantity_available": 50}
]
}' | Field | Type | Required | Description |
|---|---|---|---|
site_id | string | Yes | Site ID |
name | string | Yes | Event name |
event_type | string | Yes | single, multi_day, or series |
start_at | datetime | Yes | Event start time (ISO 8601) |
end_at | datetime | No | Event end time |
capacity | integer | Yes | Max attendees |
tiers | array | No | Ticket tiers (name, price in cents, quantity_available) |
refund_policy | string | No | flexible, moderate, strict, or none |
PATCH /events/{id}
Update an event's details, status, or settings.
DELETE /events/{id}
Delete an event. Fails if there are active tickets.
POST /events/{id}/publish
Publish an event. Requires at least one ticket tier.
Courses
Create and manage online courses with modules and lessons.
GET /courses
List courses. Filter by ?status=draft, ?status=published, ?status=archived.
GET /courses/{id}
Get a course with modules, lessons, and linked product info.
POST /courses
Create a course.
| Field | Type | Required | Description |
|---|---|---|---|
title | string | Yes | Course title |
description | string | No | Full description |
enrollment_type | string | Yes | open, paid, or invite_only |
instructor_name | string | No | Instructor name |
difficulty_level | string | No | beginner, intermediate, or advanced |
product_id | string | No | Linked product for paid enrollment |
PATCH /courses/{id}
Update a course. Supports all create fields plus status, certificate_enabled, drip_enabled, discussion_enabled.
DELETE /courses/{id}
Archive a course (soft delete).
Products
Manage your product catalog for e-commerce.
GET /products
List products. Filter by ?status=active, ?collection=ID, ?search=term.
GET /products/{id}
Get a product with variants and collection associations.
POST /products
Create a product.
curl -X POST https://my.blendo.com/api/v1/products \
-H "Authorization: Bearer optk_your_key" \
-H "Content-Type: application/json" \
-d '{
"title": "Classic T-Shirt",
"product_type": "physical",
"price": 2999,
"description": "100% organic cotton.",
"track_inventory": true,
"inventory_quantity": 50,
"tags": ["clothing", "summer"]
}' | Field | Type | Required | Description |
|---|---|---|---|
title | string | Yes | Product title |
product_type | string | Yes | physical, digital, or service |
price | integer | Yes | Price in cents |
description | string | No | Product description |
compare_at_price | integer | No | Original price (for showing savings) |
images | array | No | Array of image URLs |
tags | array | No | Tag array |
track_inventory | boolean | No | Enable inventory tracking |
inventory_quantity | integer | No | Stock count |
billing_type | string | No | one_time or recurring |
billing_interval | string | No | weekly, monthly, or yearly (for recurring) |
access_type | string | No | none, lifetime, or subscription |
PATCH /products/{id}
Update a product. Supports all create fields plus status (draft, active, archived) and a variants array for managing product variants inline.
DELETE /products/{id}
Archive a product (soft delete).
Orders
View and manage customer orders.
GET /orders
List orders. Filter by ?status=, ?date_from=, ?date_to=, ?search= (email or order number).
GET /orders/{id}
Get a single order with line items, customer, addresses, and fulfillment details.
PATCH /orders/{id}/fulfill
Mark an order (or specific items) as fulfilled.
curl -X PATCH https://my.blendo.com/api/v1/orders/01J5ORD.../fulfill \
-H "Authorization: Bearer optk_your_key" \
-H "Content-Type: application/json" \
-d '{
"tracking_company": "USPS",
"tracking_number": "9400111899223...",
"tracking_url": "https://tools.usps.com/go/TrackConfirmAction?tLabels=9400111899223..."
}' PATCH /orders/{id}/refund
Refund an order (full or partial).
curl -X PATCH https://my.blendo.com/api/v1/orders/01J5ORD.../refund \
-H "Authorization: Bearer optk_your_key" \
-H "Content-Type: application/json" \
-d '{"amount": 2999, "reason": "Customer requested"}' PATCH /orders/{id}/cancel
Cancel an order. Restores inventory for tracked products.
Discounts
Create discount codes for your store.
GET /discounts
List discounts. Filter by ?active=true or ?active=false.
POST /discounts
Create a discount code.
| Field | Type | Required | Description |
|---|---|---|---|
title | string | Yes | Internal name |
code | string | No | Discount code (auto-generated if omitted) |
type | string | Yes | percentage, fixed_amount, or free_shipping |
value | integer | Yes | Percentage (e.g. 20 = 20%) or fixed amount in cents |
minimum_amount | integer | No | Minimum cart total in cents |
usage_limit | integer | No | Max total uses |
once_per_customer | boolean | No | Limit to one use per customer |
starts_at | datetime | No | Activation date |
ends_at | datetime | No | Expiration date |
PATCH /discounts/{id}
Update a discount.
DELETE /discounts/{id}
Delete a discount.
Collections
Organize content and products into collections with custom schemas.
GET /collections
List all collections with entry counts.
GET /collections/{id}
Get a collection with schema, settings, and entry count.
POST /collections
Create a collection.
| Field | Type | Required | Description |
|---|---|---|---|
site_id | string | Yes | Site ID |
name | string | Yes* | Collection name (*required unless using a preset) |
preset | string | No | Create from a preset template |
schema | array | No | Custom field schema |
PATCH /collections/{id}
Update a collection's name, description, schema, or settings.
DELETE /collections/{id}
Delete a collection and all its entries.
GET /collections/{id}/entries
List entries in a collection (paginated).
POST /collections/{id}/entries
Create an entry in a collection.
curl -X POST https://my.blendo.com/api/v1/collections/01J5COL.../entries \
-H "Authorization: Bearer optk_your_key" \
-H "Content-Type: application/json" \
-d '{
"data": {
"name": "Featured Article",
"url": "https://example.com/article",
"description": "A great read about..."
},
"status": "published"
}' PATCH /entries/{id}
Update an entry's data, status, or sort order.
DELETE /entries/{id}
Delete an entry.
Booking
Manage services, staff, locations, customers, and appointments for scheduling-based businesses.
Booking Services
| Method | Endpoint | Description |
|---|---|---|
| GET | /booking/services | List booking services |
| POST | /booking/services | Create a service |
| GET | /booking/services/{id} | Get a service |
| PATCH | /booking/services/{id} | Update a service |
| DELETE | /booking/services/{id} | Delete a service |
Booking Staff
| Method | Endpoint | Description |
|---|---|---|
| GET | /booking/staff | List staff members |
| POST | /booking/staff | Add a staff member |
| GET | /booking/staff/{id} | Get staff details |
| PATCH | /booking/staff/{id} | Update staff |
| DELETE | /booking/staff/{id} | Remove staff |
Booking Locations
| Method | Endpoint | Description |
|---|---|---|
| GET | /booking/locations | List locations |
| POST | /booking/locations | Create a location |
| GET | /booking/locations/{id} | Get a location |
| PATCH | /booking/locations/{id} | Update a location |
| DELETE | /booking/locations/{id} | Delete a location |
Customers
Unified customer records across bookings, forms, and commerce.
GET /customers
List customers. Search by ?search= (name, email, or phone).
GET /customers/{id}
Get a customer with full details including lifetime spend, visit count, and no-show count.
POST /customers
Create a customer.
PATCH /customers/{id}
Update a customer.
DELETE /customers/{id}
Delete a customer.
Appointments
Schedule and manage appointments.
GET /appointments
List appointments. Filter by ?status=, ?date=, ?date_from=, ?date_to=, ?staff_id=.
GET /appointments/{id}
Get a single appointment with service, staff, customer, and location details.
POST /appointments
Create an appointment.
PATCH /appointments/{id}
Update an appointment.
POST /appointments/{id}/cancel
Cancel an appointment.
POST /appointments/{id}/complete
Mark an appointment as completed.
POST /appointments/{id}/assign
Assign a staff member to an appointment.
Bookings & Insights (AI-Queryable)
These endpoints are designed for AI agent integration, returning pre-formatted data for conversational interfaces.
GET /bookings
List bookings with related service, staff, customer, and location data. Filter by ?status=, ?date=, ?staff_id=, ?since=.
GET /bookings/dispatch
Get current dispatch state for home service businesses — pending assignments, in-progress jobs, staff availability.
GET /bookings/stats
Booking statistics: today's bookings, revenue, utilization, no-show rate.
POST /bookings/{id}/assign
Assign a technician/staff member to a dispatch booking.
GET /customers
List customers (same as Customers section).
GET /form-submissions
List form submissions (for AI context).
GET /links
List short links created by the account.
POST /links
Create a short link.
GET /insights
Get AI-generated business insights.
GET /score
Get the business health score.
GET /revenue-feed
Revenue event feed (payments, refunds, tips).
GET /brief
Get the daily business brief (summary of today's activity, upcoming appointments, pending tasks).
API Keys
Manage API keys programmatically.
GET /api-keys
List all API keys for your account. Returns: id, name, key_prefix, scopes, is_system, last_used_at, last_used_ip, request_count, expires_at, created_at.
curl https://my.blendo.com/api/v1/api-keys \
-H "Authorization: Bearer optk_your_key" POST /api-keys
Create a new API key.
curl -X POST https://my.blendo.com/api/v1/api-keys \
-H "Authorization: Bearer optk_your_key" \
-H "Content-Type: application/json" \
-d '{
"name": "CI/CD Deploy Key",
"scopes": ["write"],
"expires_in_days": 90
}' | Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Key name (max 255) |
scopes | array | No | Permission scopes (e.g. ["read"]) |
expires_in_days | integer | No | Auto-expire after N days (1-365) |
Response (201):
{
"data": {
"id": 42,
"name": "CI/CD Deploy Key",
"key": "optk_abc123def456...",
"key_prefix": "optk_abc1",
"scopes": ["write"],
"expires_at": "2026-07-05T10:00:00Z"
}
} DELETE /api-keys/{id}
Revoke an API key. Takes effect immediately — all requests using this key will fail.
GET /api-keys/{id}/usage
Get usage statistics for a key: total request count, last used timestamp, and last used IP.
{
"data": {
"id": 42,
"name": "CI/CD Deploy Key",
"request_count": 1847,
"last_used_at": "2026-04-06T08:32:00Z",
"last_used_ip": "203.0.113.42",
"created_at": "2026-04-01T10:00:00Z"
}
}