# Apply a Custom Link bulk action
Source: https://docs.hihobbes.com/api-reference/apply-custom-link-actions
api-reference/openapi.json POST /api/v1/custom-links/actions
Activate, deactivate, or move up to 500 Custom Links.
Requires `custom_links:write`.
Use one action per request. Moving links accepts a campaign reference; deleting
a campaign later unfiles those links without deleting them.
# Apply Playbook suggestions
Source: https://docs.hihobbes.com/api-reference/apply-playbook-suggestions
api-reference/openapi.json POST /api/v1/playbook/suggestions/{group_id}/apply
Apply selected stored suggestion payloads exactly as generated.
Requires `playbook:write`.
Send the selected suggestion IDs and their generation revision. Set
`expectedSectionsEtag` to the current `sectionsEtag`. Use the preview endpoint
instead when the proposed wording needs to be edited before it is applied to
staging.
# Apply a Playbook update preview
Source: https://docs.hihobbes.com/api-reference/apply-playbook-update
api-reference/openapi.json POST /api/v1/playbook/update-previews/{preview_id}/apply
Apply an approved, unexpired preview to staging.
Requires `playbook:write`.
The preview must have been created by the same API key. If staging changed
after the preview was created, Hobbes returns `409` without creating a version.
Create a new preview against the current `sectionsEtag`. Repeating a successful
apply returns the original result.
# Cancel a Custom Link job
Source: https://docs.hihobbes.com/api-reference/cancel-custom-link-job
api-reference/openapi.json POST /api/v1/custom-link-jobs/{job_id}/cancel
Request cancellation of unfinished job items.
Requires `custom_links:write`.
Cancellation is best effort. Work already completed remains available and
consumed creation or render quota is not refunded.
# Create a Custom Link campaign
Source: https://docs.hihobbes.com/api-reference/create-custom-link-campaign
api-reference/openapi.json POST /api/v1/custom-link-campaigns
Create a campaign for organizing Custom Links.
Requires `custom_links:write`.
Use the returned campaign id in creation requests, updates, filters, or bulk
move actions.
# Create Custom Links
Source: https://docs.hihobbes.com/api-reference/create-custom-links
api-reference/openapi.json POST /api/v1/custom-links
Create one to 500 personalized links as one asynchronous job.
Requires `custom_links:write` and an `Idempotency-Key` header.
The response is `202 Accepted` with a durable job, a `Location` header for
polling, and `Retry-After: 2`. Valid links can be accepted even when other items
fail validation. Read the job items for deterministic per-input outcomes.
# Delete a Custom Link campaign
Source: https://docs.hihobbes.com/api-reference/delete-custom-link-campaign
api-reference/openapi.json DELETE /api/v1/custom-link-campaigns/{campaign_id}
Delete a campaign and unfile its Custom Links.
Requires `custom_links:write`.
Deleting a campaign does not delete or deactivate its Custom Links. The response
reports how many links were unfiled.
# Retrieve an account
Source: https://docs.hihobbes.com/api-reference/get-account
api-reference/openapi.json GET /api/v1/accounts/{domain}
Return one account rollup by registrable domain.
Requires `accounts:read`.
Pass the registrable business domain, such as `acme.example`, not a full URL or
email address. URL-encode the value before constructing the request path.
# Poll an agent publish job
Source: https://docs.hihobbes.com/api-reference/get-agent-publish-job
api-reference/openapi.json GET /api/v1/agent/publish-jobs/{job_id}
Return publish status, a safe failure reason, and the production link after success.
Requires `agent:publish`.
Store the response `ETag`, send it as `If-None-Match` on the next poll, and honor
`Retry-After`. An unchanged job returns `304 Not Modified`. A failed job does
not change production.
# Retrieve a Custom Link
Source: https://docs.hihobbes.com/api-reference/get-custom-link
api-reference/openapi.json GET /api/v1/custom-links/{link_id}
Return one Custom Link with its thumbnail and engagement state.
Requires `custom_links:read` or `custom_links:write`.
Use the returned `url` for the published experience. A `404` means the link does
not exist in the API key's organization.
The `engagement.stage` value advances monotonically from `not_opened` to
`opened`, `started`, and `engaged`. Lead and meeting fields are conversion
flags; they are not additional engagement stages. Lower-funnel conversion
evidence can advance the lifecycle when an earlier browser event was missed.
# Retrieve a Custom Link campaign
Source: https://docs.hihobbes.com/api-reference/get-custom-link-campaign
api-reference/openapi.json GET /api/v1/custom-link-campaigns/{campaign_id}
Return one campaign and its Custom Link count.
Requires `custom_links:read` or `custom_links:write`.
A `404` means the campaign does not exist in the API key's organization.
# Retrieve campaign engagement
Source: https://docs.hihobbes.com/api-reference/get-custom-link-campaign-engagement
api-reference/openapi.json GET /api/v1/custom-link-campaigns/{campaign_id}/engagement
Return raw Custom Link funnel and activity counts for a campaign.
Requires `custom_links:read` or `custom_links:write`.
Counts are raw observations for generated links, human loads and page views,
unique visitors, sessions, leads, meeting clicks and bookings, and bot-only
scans. `visitorCountMode` is `estimated` whenever ephemeral page views
contributed to `uniqueVisitorCount`; in that mode, `loadsPerUniqueVisitor` is
also approximate. `persistentUniqueVisitorCount` and
`ephemeralPageViewCount` remain exact raw counts.
Hobbes does not treat generated links as confirmed sends or deliveries.
Reconcile sent, delivered, and bounced totals with the outbound sending
platform before calculating upper-funnel conversion rates. UTM attribution is
available on session detail rather than aggregated in this response.
# Poll a Custom Link job
Source: https://docs.hihobbes.com/api-reference/get-custom-link-job
api-reference/openapi.json GET /api/v1/custom-link-jobs/{job_id}
Return lightweight status, progress, counters, quotas, and timestamps.
Requires `custom_links:read` or `custom_links:write`.
Store the response `ETag` and send it as `If-None-Match` on the next poll.
Unchanged jobs return `304 Not Modified`. Begin at a two-second interval and
back off to five seconds after 30 seconds.
# Retrieve funnel metrics
Source: https://docs.hihobbes.com/api-reference/get-metrics
api-reference/openapi.json GET /api/v1/metrics
Return aggregate funnel performance for a trailing day window.
Requires `analytics:read`.
Choose a trailing window from 1 to 365 UTC days. The response includes session,
qualification, booking, high-intent, duration, qualification-rate, and top-source
metrics.
`qualificationRate` is already a percentage from 0 to 100, rounded to two
decimal places. Do not multiply it again in the presentation layer.
# Retrieve a person
Source: https://docs.hihobbes.com/api-reference/get-person
api-reference/openapi.json GET /api/v1/people/{email}
Return one prospect profile by exact email address.
Requires `people:read`.
Normalize the email to lowercase and URL-encode it before constructing the
request path.
```typescript theme={null}
const email = encodeURIComponent("maya@acme.example");
const path = `/api/v1/people/${email}`;
```
# Retrieve the Playbook
Source: https://docs.hihobbes.com/api-reference/get-playbook
api-reference/openapi.json GET /api/v1/playbook
Return structured staging and production Playbooks, versions, and agent links.
Requires `playbook:read`.
Use `sectionsEtag` for concurrency-safe previews. The response includes the
section catalog, exact staging and production versions, and links for testing
each agent. Legacy Playbooks are returned as read-only.
# Retrieve a session
Source: https://docs.hihobbes.com/api-reference/get-session
api-reference/openapi.json GET /api/v1/sessions/{session_id}
Return full sales analysis and tracking context for one session.
Requires `sessions:read`.
Session detail extends the list representation with qualification reasoning,
timeline events, topics, objections, next steps, summary bullets, duration, and
complete attribution context.
For sessions reached through a Custom Link, `lifecycle` contains the observed
Opened, Started, Engaged, lead, and meeting events. This lifecycle is separate
from `timelineEvents`, which remains the conversation-milestone timeline.
Session detail is also the authoritative source for acquisition attribution.
Read `tracking.utmSource`, `tracking.utmCampaign`, `tracking.utmMedium`,
`tracking.utmTerm`, and `tracking.utmContent`. Custom Link and campaign
engagement responses do not aggregate UTM values.
A `404` means the session is unavailable to the key's organization or its
analysis is not available.
# Retrieve a session transcript
Source: https://docs.hihobbes.com/api-reference/get-transcript
api-reference/openapi.json GET /api/v1/sessions/{session_id}/transcript
Return ordered conversation turns for one session.
Requires `transcripts:read`.
Entries are ordered by `sequenceNumber`. A successful request consumes one of
the organization's 2,000 daily transcript reads. Invalid ids and `404` responses
do not consume quota.
Transcript text can contain prospect PII. Prefer derived session fields unless
the integration needs the original conversation.
# List accounts
Source: https://docs.hihobbes.com/api-reference/list-accounts
api-reference/openapi.json GET /api/v1/accounts
Return B2B engagement rollups by email domain.
Requires `accounts:read`.
Accounts are ordered by `lastSeenAt`, newest first. Each record aggregates
known people, sessions, bookings, qualified people, high-intent people, time
spent, and an account summary.
The `search` parameter performs a case-insensitive partial domain match.
# List Custom Link campaigns
Source: https://docs.hihobbes.com/api-reference/list-custom-link-campaigns
api-reference/openapi.json GET /api/v1/custom-link-campaigns
Return campaigns and their Custom Link counts.
Requires `custom_links:read` or `custom_links:write`.
Campaigns organize Custom Links and correspond to the folders used by Context
Pack imports in Hobbes.
# List Custom Link job items
Source: https://docs.hihobbes.com/api-reference/list-custom-link-job-items
api-reference/openapi.json GET /api/v1/custom-link-jobs/{job_id}/items
Return per-link creation, validation, URL, and thumbnail outcomes.
Requires `custom_links:read` or `custom_links:write`.
Items remain in deterministic input order. Each item has independent creation
and thumbnail statuses, so a terminal job can still contain item-level errors.
# List Custom Link jobs
Source: https://docs.hihobbes.com/api-reference/list-custom-link-jobs
api-reference/openapi.json GET /api/v1/custom-link-jobs
Return durable Custom Link job history, newest first.
Requires `custom_links:read` or `custom_links:write`.
Use this endpoint to recover job ids after a client restart. Poll one job for
current counters and fetch its items only when the counters change.
# List Custom Link sessions
Source: https://docs.hihobbes.com/api-reference/list-custom-link-sessions
api-reference/openapi.json GET /api/v1/custom-links/{link_id}/sessions
Return sessions and lifecycle timestamps associated with one Custom Link.
Requires `custom_links:read` or `custom_links:write`.
The response contains minimal session references, lifecycle stages, timestamps,
and whether session analysis is available. It does not include transcripts,
visitor identifiers, or prospect metadata. Retrieve full analyzed session
detail with `GET /api/v1/sessions/{session_id}` and a `sessions:read` scope.
# List Custom Links
Source: https://docs.hihobbes.com/api-reference/list-custom-links
api-reference/openapi.json GET /api/v1/custom-links
Return a filterable, paginated list of Custom Links.
Requires `custom_links:read` or `custom_links:write`.
Filter by campaign, active status, engagement stage, external id, email,
company, creation date, or search text. Sort by creation time or latest
activity. Results include the published URL, thumbnail state, and engagement
rollup.
`loadCount` counts accepted non-bot load events; `pageViewCount` deduplicates
them by page-view id. `uniqueVisitorCount` uses persistent anonymous browser
continuity where storage is available and includes ephemeral page views as an
estimate where it is not. Check `visitorCountMode` before interpreting the
total. When it is `estimated`, `loadsPerUniqueVisitor` is approximate.
`persistentUniqueVisitorCount` and `ephemeralPageViewCount` expose the exact
coverage inputs. `loadsPerUniqueVisitor` is null until at least one visitor is
observed.
# List top-of-funnel events
Source: https://docs.hihobbes.com/api-reference/list-funnel-events
api-reference/openapi.json GET /api/v1/funnel-events
Return pseudonymous action-click and lead-submission events for funnel reporting.
Requires `analytics:read`.
Filter by an ISO 8601 `date_from` and `date_to`, then paginate with `limit` and
`offset`. Results contain pseudonymous events that help measure drop-off before
a prospect submits an email address.
# List people
Source: https://docs.hihobbes.com/api-reference/list-people
api-reference/openapi.json GET /api/v1/people
Return prospect profiles aggregated across sessions.
Requires `people:read`.
People are ordered by `lastSeenAt`, newest first. Use intent, qualification,
date, and partial-email filters to build prospect cohorts.
Person profiles evolve as later sessions update activity, intent,
qualification, and summary fields.
# List Playbook suggestions
Source: https://docs.hihobbes.com/api-reference/list-playbook-suggestions
api-reference/openapi.json GET /api/v1/playbook/suggestions
Return ready Hobbes suggestions with evidence and exact proposed changes.
Requires `playbook:read`.
Each result is a ready suggestion group whose changes target Playbook sections.
Transcript evidence is included only when the key also has `transcripts:read`.
# List sessions
Source: https://docs.hihobbes.com/api-reference/list-sessions
api-reference/openapi.json GET /api/v1/sessions
Return analyzed production sessions, newest first.
Requires `sessions:read`.
Combine qualification, intent, booking, date, and email filters to build routing
or synchronization cohorts. Status filters accept comma-separated values.
Results include analyzed production sessions only. Use the session `id` as an
idempotency key in downstream systems.
# Preview a Playbook update
Source: https://docs.hihobbes.com/api-reference/preview-playbook-update
api-reference/openapi.json POST /api/v1/playbook/update-previews
Validate proposed changes and return a before-and-after summary without changing staging.
Requires `playbook:write`.
Send restricted JSON Patch operations and a stable `operationKey`. Set
`expectedSectionsEtag` to the current `sectionsEtag`. Hobbes validates the
changes against a clone of staging.
The preview does not change the Playbook and expires after 24 hours.
# Queue an agent publish
Source: https://docs.hihobbes.com/api-reference/publish-agent-version
api-reference/openapi.json POST /api/v1/agent/publish-jobs
Run tests and publish the exact current staging version after confirmation.
Requires `agent:publish`.
Send the current staging version, a stable `operationKey`, and
`confirmation: "publish_to_production"` only after the user explicitly approves
that exact version. Hobbes runs the existing conversation tests before changing
production and returns `202 Accepted` with a job to poll.
# Regenerate a Custom Link thumbnail
Source: https://docs.hihobbes.com/api-reference/regenerate-custom-link-thumbnail
api-reference/openapi.json POST /api/v1/custom-links/{link_id}/thumbnail-jobs
Create an asynchronous thumbnail regeneration job.
Requires `custom_links:write` and an `Idempotency-Key` header.
An explicit regeneration consumes one render unit. Poll the returned job instead
of repeatedly submitting the operation.
# Retry Custom Link job items
Source: https://docs.hihobbes.com/api-reference/retry-custom-link-job
api-reference/openapi.json POST /api/v1/custom-link-jobs/{job_id}/retry
Create a child job for failed or selected items.
Requires `custom_links:write` and an `Idempotency-Key` header.
Choose failed items or provide selected item ids. Explicit thumbnail retries
consume new render units; automatic internal retries do not.
# Update a Custom Link
Source: https://docs.hihobbes.com/api-reference/update-custom-link
api-reference/openapi.json PATCH /api/v1/custom-links/{link_id}
Update personalization, sharing metadata, campaign, or active state.
Requires `custom_links:write`.
Only fields present in the request are changed. Hobbes creates a thumbnail job
only when a thumbnail-affecting field changes; those updates also require an
`Idempotency-Key` header.
# Update a Custom Link campaign
Source: https://docs.hihobbes.com/api-reference/update-custom-link-campaign
api-reference/openapi.json PATCH /api/v1/custom-link-campaigns/{campaign_id}
Rename a Custom Link campaign.
Requires `custom_links:write`.
Renaming the campaign does not change its id or the links filed in it.
# Product updates
Source: https://docs.hihobbes.com/changelog
New features, improvements, and fixes across Hobbes.
Follow what is changing across the Hobbes agent, platform, integrations, and
developer tools. Subscribe through the RSS link above to receive new updates.
## Show your product in your buyer’s language
Hobbes can now translate the product screens it shows, along with its
conversation, voice, and widget controls.
Choose a language and voice for an Agent Role, generate the localized
experience, and test it before publishing. Review and correct translations
while your current demo continues serving buyers.
## Put prospect details in the HubSpot fields your team already uses
You can now map Hobbes prospect details into HubSpot’s standard contact
properties, including names, job titles, company details, and phone numbers.
Choose where each detail should appear alongside your existing custom-field
mappings. Your team can use the same contact fields in its follow-up tools
and workflows.
## Send conversation transcripts into your workflows
Completed-session webhooks now include ordered conversation turns with
speaker labels and timestamps.
Your team can use the conversation alongside session details in follow-up
workflows, reporting, and analysis. Payloads indicate when a transcript has
been shortened, so downstream tools can handle it correctly.
## Work with Hobbes from your AI tools
Connect Claude or another compatible AI tool to Hobbes to explore demo
sessions, research prospects, and create personalized demo links.
You can also preview Playbook changes, apply them to staging, and publish an
approved agent version. Separate permissions let you choose which tools can
read your data, update your agent, or publish changes.
## Give each page the right Hobbes experience
Agent Roles let you tailor Hobbes to a specific page or personalized demo
link.
Choose the Role’s objective, which products it can show, and the screen or
slide that opens the conversation. You can also give each Role its own
preview image, so the experience fits what brought the buyer there.
## Find practical help for setup and ongoing improvements
The Customer Hub now brings setup, installation, CRM connections, publishing,
and coaching guides together in one place.
Follow the steps for getting Hobbes onto your website, connecting your sales
tools, and reviewing the agent before it goes live. Return as your needs
change to learn how to update content and improve the demo experience.
[Explore the Customer Hub](/customer-hub/index).
## Bring personalized demo previews to life
Newly generated campaign previews can now preserve an animated demo and
incorporate the prospect’s logo.
Use an animated source to show a glimpse of your product in the preview
shared with each account. Existing previews stay as they are until you
generate a new one.
## Show multiple products in one conversation
Hobbes can now move between multiple products during the same demo.
When a buyer’s question spans your product suite, Hobbes can find relevant
screens and walkthroughs across the available products and move between them
as the conversation develops.
## Make walkthroughs easier to build and explore
You can now pause a product capture and resume when you are ready. Review
saved screens as you work, with clearer confirmation of what has been
captured.
Buyers also have more control while exploring. Home returns them to the
opening screen, and Explain this screen lets them ask Hobbes about the screen
they just opened.
## Train Hobbes with your existing sales decks
You can now upload PowerPoint files directly when adding slides or sales
decks to Hobbes.
Use your existing PPTX files during setup or when adding background
materials. Hobbes processes the deck for you, so your team does not need to
export a PDF first.
## Coach Hobbes while you test a demo
You can now leave feedback while testing a walkthrough. Point out an
incorrect explanation, flag a screen that should not appear, or tell Hobbes
what deserves more attention.
Feedback stays connected to the screen and moment you were reviewing. Review
your notes together, then use them to rebuild the walkthrough and test the
changes.
## Know who is exploring while the demo is happening
Turn on live session notifications to receive enriched visitor details in
Slack while a demo is still in progress.
See who is exploring as their contact and company details become available.
The completed-session summary arrives separately after the conversation has
been analyzed, giving your team the context for its follow-up.
## Follow each demo link from first open to conversation
Personalized demo links now have a lifecycle timeline showing when a buyer
opened the link, started a demo, engaged, or booked a meeting.
Review visitor counts and automated scans alongside the campaign’s
engagement, then open the sessions associated with a specific link. Your
team can follow the activity from the campaign down to the conversation.
## Review suggested improvements and unanswered questions in one place
The Inbox now brings suggested Playbook updates and unanswered questions
together. Review the changes that are ready for a decision and choose what
to apply.
Curated Answers gives your team a place to inspect saved answers, their
sources, and their history. Retire an outdated answer when Hobbes should
stop using it, while keeping the record available for review.
## Give ready-to-buy prospects a direct next step
When a buyer asks to purchase, Hobbes can now direct them to your pricing or
checkout page.
Set the purchase page your team wants buyers to use. Hobbes can offer that
next step during the conversation, with a link buyers can open to continue
on your website.
## Understand qualification across a prospect’s conversations
Hobbes now assesses qualification at the prospect level and brings together
buying intent from their recent demo conversations.
Define your qualification criteria, review the reasoning behind each
assessment, and override a result when your team has additional context.
Criteria history lets you review changes and restore an earlier version.
## Replay what your buyers actually saw
Session replay now brings the conversation and product walkthrough together.
Watch the screens a buyer saw, follow agent and visitor clicks, and review
the audio and transcript on the same timeline. Your team can see where
buyers explored, what they asked, and where the experience needs attention.
## Create personalized demo links from your own workflows
Use the Custom Links API to create up to 500 personalized demo links in one
job, organize them into campaigns, and generate the thumbnails buyers see
when links are shared. This gives your team a programmatic path for launching
personalized outreach without relying on spreadsheet imports.
Track each job as it runs, inspect individual results, and retry or cancel
unfinished work. Separate read and write permissions let administrators
control which API keys can view or manage links. [Read the Custom Links
guide](/guides/custom-links).
## Keep Salesforce and Pipedrive up to date after every demo
Connect Hobbes to Salesforce or Pipedrive and choose which demo sessions
should sync. Map prospect, company, and conversation details to the right CRM
fields, so each record reflects what happened in Hobbes.
Hobbes can add session summaries and follow-up activity after a demo, while
the Activity view shows what synced and where something needs attention.
Configure each connection to match the way your sales team works.
## Guide buyers through the right product flow
Hobbes can show captured product screens while it explains a workflow.
Walkthroughs begin from the screen a buyer is already viewing, so the
experience stays focused instead of restarting from the beginning.
Buyers can keep exploring between steps, and Hobbes can hold on the current
screen when navigation is not needed. Clearer click targets and smoother
screen changes make each walkthrough easier to follow.
## More useful lead context, wherever your team works
Hobbes now gives your sales team more context about every prospect.
Connect Hobbes to HubSpot or Attio and choose which details you want to send.
New leads can include their role, company, location, direct phone number,
interests, objections, and a summary of the conversation.
Slack notifications now bring the most important lead and company details
together in one cleaner update, so your team can decide who to follow up with
without digging through the full conversation.
We also improved phone matching. New lookups now prioritize direct and mobile
numbers while filtering out company main lines and support numbers.
## Everything you need to build with Hobbes
The new Hobbes Documentation makes it easier to bring what Hobbes learns into
the tools your team already uses.
Developers can retrieve demo sessions, prospects, accounts, transcripts, and
performance metrics. The documentation also includes practical guides for
sending qualified leads to a CRM, building reports, exporting data, and
finding high-intent prospects.
We also published a dedicated guide that coding agents can use when working
with Hobbes.
[Explore the Hobbes Documentation](/)
## Shape what Hobbes knows and how it speaks
You now have more direct control over your Hobbes agent.
Knowledge sources can refresh on a schedule, so Hobbes stays current as your
product and documentation change. You can choose how often each source
refreshes and decide whether Hobbes should publish those updates automatically.
You can also review and edit the agent's playbook before publishing a new
version.
For voice conversations, you can adjust the agent's conversation style and
response length, preview the changes, and decide when they should go live.
## See which prospects engage with your outbound demos
You can now see what happens after you send a personalized demo campaign.
See who opened their link, started a demo, became a lead, or booked a meeting.
Search and filter the campaign to find your most engaged prospects, then open
their Hobbes session to understand what caught their attention.
This turns personalized demo links into a clear list of people your sales team
should follow up with.
## Control who can open your demos
You can now keep competitors and unwanted visitors out of your Hobbes demos.
Block an entire company domain or one specific email address. Add entries one
at a time or import a list from a spreadsheet.
Blocked visitors see a simple unavailable message that does not reveal why
they were denied access. If Hobbes blocks someone, they cannot immediately try
again with another email from the same browser.
## Hobbes now responds up to 80% faster
Voice conversations with Hobbes now feel much more natural.
In our testing, standard voice replies started in about 1.3 seconds, compared
with 4 to 7 seconds before. Prospects spend less time waiting and more time
exploring your product.
We also improved the rest of the voice experience:
* Prospects can hear the opening greeting before granting microphone access.
* Hobbes asks for microphone access after the greeting.
* Typing a message or choosing a suggestion immediately stops the previous reply.
* Prospects can control their microphone and speaker separately.
## See what brought each buyer to Hobbes
Hobbes now connects a buyer's first website visit to the demo conversation
that follows.
See where a visitor came from and which Hobbes session they eventually
started. Hobbes can also identify traffic from paid LinkedIn campaigns and
show clearer source names throughout the dashboard.
This gives your team a better view of which channels bring in real demo
conversations, not just clicks.
## Clean up and trim your demo content faster
Managing demo content now takes fewer clicks.
Select multiple clips or slides at once when you want to organize or remove
content. When a clip needs adjustment, trim it with a visual preview and
choose the exact moment where it should start and end.
Hobbes refreshes the clip and its preview after you save, so you can review
the finished result immediately.
## Know who your prospects are before you follow up
Hobbes now gives you a clearer picture of the people exploring your product.
Prospect profiles can include their name, role, company, location, LinkedIn
profile, company details, and direct phone number. You can see this context
from the People page or directly from a demo session.
Your team can understand who a prospect is and prepare a relevant follow-up
without researching them from scratch.
## Create personalized demos for an entire campaign
You can now create personalized demo links in bulk.
Upload a spreadsheet and Hobbes creates one demo link for every prospect.
Organize links into campaigns, use your own domain, and personalize the title,
description, and preview image each person sees when the link gets shared.
When the campaign is ready, download the finished links and add them to your
outbound tool.
## Keep Hobbes up to date automatically
Hobbes can now refresh your product documentation on a schedule.
Choose whether each source should refresh daily, weekly, or monthly. You can
also choose when updates happen and whether Hobbes should publish them
automatically.
As your product and documentation change, your agent can stay current without
someone manually checking every source.
## Send the right lead data to HubSpot
You can now connect Hobbes directly to HubSpot.
Choose which demo sessions Hobbes sends, then decide where each prospect,
company, and conversation detail should appear. Hobbes can create new
contacts, update existing ones, and keep your CRM current after every
qualified demo.
This gives your sales team the full story before they follow up, without
copying information between tools.
## Your Ask Hobbes conversations now stay organized
Each Ask Hobbes question now lives in its own private conversation.
Reopen previous conversations, continue where you left off, rename important
threads, or delete ones you no longer need.
Hobbes keeps each conversation's context separate, so one analysis does not
affect another.
## Manage your agent's knowledge in one place
Agent Knowledge now brings your product materials, uploaded content, key
terms, and test conversations together in one place.
It is now easier to keep the agent's information organized, test how Hobbes
handles important questions, and see what needs attention before prospects
encounter it.
## Make Hobbes feel at home on your website
You now have more control over how the Hobbes launcher appears on your
website, including its placement, thumbnail, wordmark, and icon style.
We also made the setup instructions clearer, so your team can review the
experience and get Hobbes live with less back and forth.
## Personalize every demo link
You can now create demo links that include context about a specific buyer or
account before they open Hobbes.
Use them for outbound campaigns, follow-ups, or account-specific walkthroughs.
Hobbes can start with what you already know and give each prospect a more
relevant conversation from the first question.
## Turn missed questions into better answers
When Hobbes struggles with a question, it now gives your team a clearer path
to improve the answer.
Add a better source, provide the right answer, capture the missing part of
your product, or adjust how the agent should respond. Your team can review
what happened, choose the right fix, and keep track of the improvement.
# Build with Hobbes
Source: https://docs.hihobbes.com/developers/index
Connect Hobbes intelligence, Custom Links, Playbook updates, and AI clients to your systems.
The Hobbes API gives your systems an organization-scoped view of the buying
signals captured during autonomous product demos. Query analyzed sessions,
prospect histories, account engagement, transcripts, and funnel metrics. You
can also create personalized Custom Links, update the Playbook in staging, and
publish an approved agent version.
Create a scoped API key and retrieve your first qualified sessions.
Review every endpoint, parameter, response field, and failure mode.
Connect supported AI clients to the Hobbes MCP server.
Create personalized links and track thumbnail jobs.
Preview Playbook changes in staging and publish an approved agent version.
## What you can build
| Resource | Use it for | Scope |
| - | - | - |
| Sessions | Qualification, intent, summaries, objections, topics, and attribution | `sessions:read` |
| Transcripts | Ordered conversation turns for selected sessions | `transcripts:read` |
| People | Prospect histories aggregated across sessions | `people:read` |
| Accounts | Company-level engagement rolled up by email domain | `accounts:read` |
| Metrics | Funnel performance over a trailing time window | `analytics:read` |
| Custom Links | Personalized links, campaigns, thumbnails, and asynchronous jobs | `custom_links:read`, `custom_links:write` |
| Playbook | Staging and production guidance, version-safe updates, and suggestions | `playbook:read`, `playbook:write` |
| Agent publishing | Publish the exact staged agent after confirmation and tests | `agent:publish` |
Every API key belongs to one Hobbes organization. The organization is derived
from the key, never accepted from a request parameter, and every query is
scoped to that organization.
The API only returns analyzed production sessions. A newly completed demo may
not appear until its analysis finishes.
## Base URL
```text theme={null}
https://api-us.hihobbes.com/api/v1
```
Version 1 is additive. Hobbes may add response fields, but existing v1 fields
will not be removed or renamed. See [versioning and compatibility](/guides/versioning).
# Use Hobbes with AI agents
Source: https://docs.hihobbes.com/guides/ai-agents
Install the Hobbes API skill so coding agents can read data and make guarded Playbook updates.
The Hobbes API skill gives AI coding agents reviewed instructions for reading
Hobbes data, updating the Playbook in staging, and publishing an explicitly
approved agent version. It includes the endpoint map, scope requirements,
pagination rules, preview safeguards, and publishing confirmation boundary.
Review the complete agent instructions before installing the skill.
## Install the skill
Use a client that supports the open Agent Skills format:
```bash theme={null}
npx skills add https://docs.hihobbes.com --list
npx skills add https://docs.hihobbes.com
```
The listing shows `hobbes-read-api`. The package keeps this existing identifier
for compatibility with earlier installations. If it still shows the older
`hobbes` entry immediately after a documentation deployment, wait for
Mintlify's skill discovery cache to refresh before installing it.
The hosted skill and its discovery metadata stay synchronized with this
documentation.
## Provide credentials safely
Create a minimum-scope key in Hobbes Settings, then provide it to the agent's
server-side environment:
```bash theme={null}
read -s HOBBES_API_KEY
export HOBBES_API_KEY
```
Do not paste a key into an agent conversation, commit it to a repository, or
place it in browser code. Remove it from the shell when the task is complete:
```bash theme={null}
unset HOBBES_API_KEY
```
## Example requests
Ask an agent to use the installed skill for tasks such as:
* "Use the Hobbes Read API to incrementally sync qualified sessions into our CRM."
* "Export the last seven days of Hobbes sessions to newline-delimited JSON."
* "Find recently active high-intent prospects and rank them by `lastSeenAt`."
* "Retrieve one selected session transcript and preserve request IDs on errors."
* "Preview a change to our Playbook opening and show me the summary before applying it."
* "After I approve the exact staged version, publish it and report whether the tests passed."
The skill tells the agent how to build or review the integration. It does not
contain an API key, grant access to an organization, or bypass the confirmation
required before a Playbook change or production publish.
## Machine-readable resources
* [Agent skill](/.well-known/agent-skills/hobbes-read-api/SKILL.md)
* [Documentation index](/llms.txt)
* [Complete documentation context](/llms-full.txt)
* [OpenAPI specification](/api-reference/openapi.json)
Use the OpenAPI specification as the field-level contract. The skill provides
the workflow and safety rules that an API schema alone cannot express.
# Authentication and scopes
Source: https://docs.hihobbes.com/guides/authentication
Create, store, scope, rotate, and revoke organization API keys.
Hobbes authenticates server-to-server requests with organization-scoped API
keys. Keys begin with `hb_live_` and should be handled like passwords.
## Send a key
Use a Bearer authorization header:
```http theme={null}
Authorization: Bearer hb_live_...
```
If your integration cannot set a Bearer header, use `x-api-key` instead:
```http theme={null}
x-api-key: hb_live_...
```
Do not send both. Bearer authentication takes precedence when both are present.
## Choose scopes
| Scope | Access | Default |
| - | - | - |
| `sessions:read` | Session lists and detailed sales analysis | On |
| `people:read` | Prospect profiles aggregated across sessions | On |
| `accounts:read` | Account rollups by registrable email domain | On |
| `analytics:read` | Aggregate funnel metrics | On |
| `custom_links:read` | Custom Links, campaigns, jobs, and item results | Off |
| `custom_links:write` | Create and manage Custom Links and thumbnails; includes read access | Off |
| `transcripts:read` | Raw conversation turns | Off |
| `playbook:read` | Staging and production Playbooks, versions, links, and ready suggestions | Off |
| `playbook:write` | Preview and apply Playbook changes to staging | Off |
| `agent:publish` | Publish the exact current staging version after confirmation and tests | Off |
Create separate keys for separate integrations. A warehouse export does not
need transcript access, and a transcript processor does not necessarily need
account or metrics access.
Optional scopes are not added to existing keys automatically. Create or rotate
to a key that explicitly carries the minimum required scopes.
Keep Playbook access separate from production publishing when possible. A key
with `playbook:write` can update staging without changing the production agent.
Add `agent:publish` only when the integration must publish after an explicit
confirmation and successful conversation tests.
Transcript text can contain prospect PII. Enable `transcripts:read` only for
systems that need raw text and apply your normal retention and access rules.
## Rotate a key
1. Create a replacement key with the same minimum scopes.
2. Deploy the replacement to your integration.
3. Confirm successful requests with the replacement key.
4. Revoke the old key in Hobbes.
Revocation takes effect immediately. Keep the old key active only for the
short overlap required to complete the deployment.
## Authentication failures
| Status | Meaning | Action |
| - | - | - |
| `401` | Key is missing, malformed, invalid, or revoked | Check the header and replace the key |
| `403` | Key is valid but lacks the endpoint's scope | Create a correctly scoped key |
Hobbes returns the same organization-safe `404` for resources that do not exist
and resources owned by another organization.
# Hobbes for ChatGPT support
Source: https://docs.hihobbes.com/guides/chatgpt-plugin-support
Get help managing Hobbes product agents, reviewing demo data, and creating personalized links in ChatGPT.
Hobbes brings your product agents into ChatGPT. Inspect agent playbooks and
versions, review demo conversations, preview behavior changes, and apply
approved updates to a draft. You can review coaching proposals and publish
a specific approved version through Hobbes' confirmation and test flow.
You can also review demo performance, understand prospect and account
engagement, and create personalized demo links.
Watch the [Hobbes for ChatGPT walkthrough](/guides/chatgpt-plugin-walkthrough)
for a preview using a dedicated demo account.
## Get help
Email [support@hihobbes.com](mailto:support@hihobbes.com). Include the task you
were trying to complete, the error message, and whether you can still sign in
to [Hobbes](https://app.hihobbes.com).
Do not send passwords, verification codes, API keys, connection tokens, or
prospect transcripts in a support email.
## Connect your Hobbes account
Follow the Hobbes sign-in link offered by ChatGPT. Sign in with your own Hobbes
account, choose the organization to connect, and review the requested access.
Each teammate connects their own account.
The connection can read the selected organization's sessions, transcripts,
people, accounts, analytics, and demo links. An organization admin's v1
connection also permits personalized link creation. Transcript access applies
to the organization, so connect an organization whose data you are authorized
to use in ChatGPT.
Agent inspection uses `playbook:read`. Previewing and applying playbook changes
uses `playbook:write`. Coaching uses `coaching:read` and `coaching:write`;
publishing uses `agent:publish`. Choose the additional permissions for the
features you want. Agent changes, coaching, and publishing require an
organization admin. The connection acts only within the organization you choose.
ChatGPT shows proposed changes before you approve their application. Saving a
draft and publishing it are separate steps. Publishing a version requires native
confirmation and runs Hobbes' conversation-test gate. Approving a coached shared
fact also requires native confirmation because it adds organization knowledge
that every active agent Role can use.
For connection management and scope details, see
[Connect AI clients with MCP](/guides/connect-ai-clients).
## Common problems
### How do I switch organizations?
Each Hobbes connection uses one organization at a time. Changing your selected
organization in the Hobbes dashboard does not change the organization connected
to ChatGPT, and the plugin has no in-chat organization-switching action.
In Hobbes, open **Account Settings → Connected AI clients** and disconnect the
ChatGPT connection you want to change. Reconnect it from ChatGPT, select the
other organization on the Hobbes authorization page, choose the permissions you
want, and approve. Confirm that Connected AI clients shows the new organization
before requesting its records or agent updates. A routine reconnect can reuse
the previous authorization, so disconnect it in Hobbes first to choose again.
### I cannot sign in or see my organization
Confirm you can sign in to [Hobbes](https://app.hihobbes.com) and that you are a
member of the organization. If your membership changed, reconnect through the
normal sign-in flow. Contact support if the organization still does not appear.
### My new demo is missing
Hobbes returns analyzed production sessions. A completed demo may not appear
until its analysis finishes. Check the time window and filters in your request,
then check the conversation in Hobbes. If it remains missing, contact support
with the session link and error message.
### I cannot create a personalized link
Link creation requires a Hobbes organization admin and `custom_links:write`.
Ask your organization's admin to check your role and approved connection
permissions. Link creation runs as a job; wait for its final status before
retrying a request. A failed or pending job does not mean a link was created.
### I asked Hobbes to send email, update my CRM, or buy a subscription
Those actions are outside this first release. The plugin does not deliver
outreach, change CRM records, make purchases, or manage billing.
### I cannot update my product agent
Check that you are an organization admin and that your connection includes the
permissions for the requested action. Disconnect the existing ChatGPT connection
in **Account Settings → Connected AI clients**, then reconnect and select the
additional access on the Hobbes authorization page. A connection with only
demo-data permissions cannot inspect or update playbooks, coach agents, or
publish a version.
If a preview expires or the draft changes, read the current playbook and review a
fresh preview. Hobbes refuses a stale update so it does not overwrite newer work.
### I saved a change, but the live agent still uses the previous version
A saved draft has not been published. Request publication of the exact approved
draft and confirm the native prompt. Check the publish job's result. A pending or
failed job does not mean a new production version is live. A failed test gate or
a draft that changed during publication requires review before retrying.
## Remove access
In Hobbes, open **Account Settings → Connected AI clients** and disconnect the
ChatGPT connection. Removing a plugin from ChatGPT alone does not revoke its
Hobbes authorization.
## Privacy and terms
Read the [Hobbes privacy policy](https://www.hihobbes.com/privacy-policy) and
[terms of use](https://www.hihobbes.com/terms-of-use). Information returned by
Hobbes becomes available to ChatGPT for your conversation. Only request the
data needed for your task.
# Hobbes for ChatGPT walkthrough
Source: https://docs.hihobbes.com/guides/chatgpt-plugin-walkthrough
Watch Hobbes review demo conversations and preview product-agent updates in ChatGPT using a dedicated demo account.
This release preview shows the complete Hobbes plugin in ChatGPT in Chrome,
connected to a dedicated Hobbes demo organization. The recording uses
fictional people and synthetic email addresses at OpenAI, Stripe, and Figma.
These sessions do not represent those companies' activity or buying interest.
Use the player's full-screen control to read the results. The video runs
7 minutes and 26 seconds and has no audio.
## What the walkthrough shows
| Approximate time | Task |
| - | - |
| 0:00 | Review demo performance, keeping session counts and unique-person counts distinct. |
| 1:03 | Inspect a saved transcript for pricing, integration, and data-accuracy objections, then review the account's engagement. |
| 2:18 | Filter qualified, high-intent sessions and distinguish current person qualification from each session's historical result. |
| 3:08 | Inspect a product agent's draft and production versions and preview an exact playbook change. |
| 3:43 | Check earlier coaching and publish-job outcomes, then verify the agent's current content. |
| 4:18 | Poll an existing personalized-link job and review an empty analytics window. |
| 4:53 | Verify that email delivery, purchases, and Salesforce updates stay outside the plugin's capabilities. |
| 6:33 | Inspect the four packaged skills and the Hobbes submission draft with its logo. |
The playbook preview remains unapplied. The video checks the results of earlier
test changes and their restoration; it does not apply coaching, publish another
agent version, or create another personalized link during capture. Draft changes
and production publication require separate approvals.
The recording shows a private installation of the complete v0.2.0 package. The
public submission remains a draft under review preparation; this page does not
announce approval or availability in the ChatGPT store.
For connection instructions, organization switching, access removal, and help,
see [Hobbes for ChatGPT support](/guides/chatgpt-plugin-support).
# Connect AI clients with MCP
Source: https://docs.hihobbes.com/guides/connect-ai-clients
Give Claude and other AI tools permission-scoped access to Hobbes data, Playbook updates, and agent publishing.
## Overview
Hobbes runs a remote [Model Context Protocol](https://modelcontextprotocol.io) server at:
```text theme={null}
https://api.hihobbes.com/mcp
```
Connect an MCP-compatible AI client, such as Claude or Claude Code, and it can
query Hobbes data, create Custom Links, update the Playbook in staging, and
publish an approved agent version. The tools available to the client depend on
the permissions you approve.
Access is authorized with OAuth, not API keys. You sign in with your Hobbes account, choose one organization, and approve a specific set of permissions. The client only ever sees what you approved.
MCP connections are personal. Each teammate connects their own client and approves their own access. To integrate a backend system instead, use an [API key](/guides/authentication).
## Connect from Claude
In Claude, open **Settings → Connectors → Add custom connector** and enter `https://api.hihobbes.com/mcp`.
Claude opens the Hobbes sign-in page in your browser. Use your normal Hobbes account.
Pick the organization this connection may access, review the permissions,
and click **Approve**. Only an organization admin can approve Custom Link
creation, Playbook access, Playbook updates, or agent publishing.
Back in Claude, the Hobbes tools are available immediately. Try: "Which of my demo sessions this week qualified, and why?"
On a Claude Team or Enterprise plan, custom connectors are managed by a workspace admin — ask them to add the connector for your workspace.
## Connect from Claude Code
Register the server, then authenticate inside a session:
```bash theme={null}
claude mcp add --transport http hobbes https://api.hihobbes.com/mcp
```
Run `/mcp` in Claude Code, select **hobbes**, and choose **Authenticate**. The same browser sign-in and consent flow applies. Once connected, Claude Code can pull Hobbes data into any task — reports, CRM scripts, prospect research.
## Connect from other clients
Any client that supports remote MCP servers over streamable HTTP with OAuth can connect using the same URL — in Cursor, Windsurf, or VS Code, add it wherever the client configures MCP servers.
For clients that can't connect to remote MCP servers directly — they only launch MCP servers as local processes (stdio), or their remote support lacks OAuth (Codex, at the time of writing) — use the standard [`mcp-remote`](https://www.npmjs.com/package/mcp-remote) bridge. It runs locally as a small proxy and forwards everything to the Hobbes server:
```json theme={null}
{
"mcpServers": {
"hobbes": {
"command": "npx",
"args": ["mcp-remote", "https://api.hihobbes.com/mcp"]
}
}
}
```
The bridge opens the browser sign-in on first use and handles tokens from then on.
Connections made through the bridge appear as **MCP CLI Proxy** on the consent screen and in your connected clients list — that is the bridge's own registered name, not the client behind it.
## Permissions and tools
Permissions are chosen on the consent screen and fixed for the life of the connection. The client's tool list shows only the tools its permissions allow.
If you connected before Playbook and publishing permissions were available,
revoke the old connection and reconnect. Select each new permission you want to
grant. Existing connections never receive new permissions automatically.
| Permission | Tools | What the client can do |
| - | - | - |
| `sessions:read` | `list_sessions`, `get_session` | Browse demo sessions, outcomes, and qualification results |
| `transcripts:read` | `get_session_transcript` | Read full session transcripts |
| `people:read` | `list_people`, `get_person` | Look up prospects and their engagement |
| `accounts:read` | `list_accounts`, `get_account` | Look up accounts and rollups |
| `analytics:read` | `get_funnel_metrics` | Query funnel and conversion metrics |
| `custom_links:read` | `list_custom_links`, `get_custom_link`, `get_custom_link_job`, `list_custom_link_campaigns` | Inspect Custom Links, campaigns, and creation jobs |
| `custom_links:write` | `create_custom_links` | Create personalized Custom Links in batches |
| `playbook:read` | `get_playbook`, `list_playbook_suggestions` | Read staging and production Playbooks, versions, links, and ready suggestions |
| `playbook:write` | `preview_playbook_update`, `apply_playbook_update`, `apply_playbook_suggestions` | Preview changes and apply them to staging |
| `agent:publish` | `publish_agent_version`, `get_agent_publish_job` | Publish the exact staged version after confirmation and tests, then check its status |
Every tool is scoped to the organization approved at connection time. The organization is derived from the connection, never accepted from the client.
Some clients add their own approval prompt before running any tool — Claude Code's "Do you want to proceed?" or Claude's tool permission dialog. Those prompts belong to the client, not Hobbes; the permissions you approved at consent apply either way.
Transcripts contain the verbatim words of everyone in a session. Grant `transcripts:read` deliberately, and see [Transcripts and security](/guides/transcripts-security) before piping transcript text into other systems.
## Create Custom Links
`custom_links:write` allows a client to create personalized links:
* Only an **organization admin** can approve it on the consent screen.
* Batches are capped at 200 links per call and run as asynchronous jobs — the client receives a job it can poll with `get_custom_link_job`.
* Requests are idempotent and quota-checked, so a retried or repeated call cannot double-create links. Large batches can take a couple of minutes to be accepted — a client that times out and retries with the same `operation_key` receives the original job instead of duplicates.
## Update the Playbook
Playbook updates follow a preview-first process:
1. The client reads the current staging and production Playbooks with
`get_playbook`.
2. `preview_playbook_update` validates the proposed changes and returns a
before-and-after summary without changing staging.
3. After you review the summary, `apply_playbook_update` applies that exact
preview to staging. Previews expire after 24 hours, and a change to staging
invalidates an older preview.
4. Open the staging link returned by Hobbes and test the updated agent.
The client can also list ready Hobbes suggestions. Applying a suggestion uses
the exact stored change. Use the preview flow when you want to edit the wording
first.
Legacy Playbooks can be read through MCP, but they cannot be updated until they
are migrated in Hobbes.
## Publish an agent version
Publishing requires the separate `agent:publish` permission. Hobbes always:
* asks for confirmation in the AI client before creating the publish job;
* publishes the exact current staging version, not an inferred or older version;
* runs the existing conversation tests before changing production; and
* returns a job that the client checks until it succeeds or fails.
Grant `agent:publish` only when the connection should be able to change the
production agent. Playbook updates can remain limited to staging by granting
`playbook:write` without `agent:publish`.
If you want a connection that cannot change data, leave all write and publishing
permissions unselected.
## Manage and revoke connections
Every client you approve appears in **Hobbes → Account Settings → Connected AI clients**, showing its name, organization, permissions, and connection date.
Revoking a connection cuts the client's access on its **next request** — before its token expires. Reconnecting later walks through sign-in and consent again.
Removing a connector inside the AI client does **not** revoke its access — the connection stays valid until you revoke it here. This page is the source of truth for what can reach your data.
Leaving an organization revokes access automatically: tools fail for that org's connections the moment your membership ends, even mid-session.
## Limits and errors
* Requests are rate-limited per connection (HTTP `429` when exceeded); clients back off and retry automatically.
* A `401` means the token expired or the connection was revoked — reconnect from the client.
* A `403` means the connection lacks the permission for that tool, or your organization membership changed.
* A connector that shows **no tools available** after being re-added was likely revoked in between — some clients reuse their stored credentials silently instead of prompting. Refresh the connector's tool list or reconnect to re-authenticate.
## MCP or API key?
| | MCP connection | API key |
| - | - | - |
| Belongs to | One user, one organization | One organization |
| Authorization | OAuth sign-in + consent screen | Key created in Settings |
| Best for | AI assistants and agent tools used by a person | Backend services, warehouses, scheduled jobs |
| Write access | Admin-approved permissions at consent | Optional `custom_links:write`, `playbook:write`, and `agent:publish` scopes |
Both surfaces expose the same data with the same organization scoping — pick per use case, or use both.
# Create Custom Links
Source: https://docs.hihobbes.com/guides/custom-links
Create personalized links in batches, generate thumbnails, and track asynchronous jobs.
The Custom Links API creates the same personalized experiences available through
CSV Context Pack imports. One request can accept from 1 to 500 links and returns
an asynchronous job to poll.
## Create a key
Create an API key in Hobbes Settings with:
* `custom_links:write` to create and manage links, jobs, thumbnails, and campaigns
* `custom_links:read` for read-only listing and polling
Write scope also satisfies read operations. Existing keys do not receive either
scope automatically.
## Create links
Send one `POST /api/v1/custom-links` request for the entire batch. A 300-link
batch is one HTTP request, but it consumes 300 creation units and, when
`generateThumbnails` is true, up to 300 render units.
```bash theme={null}
curl "https://api-us.hihobbes.com/api/v1/custom-links" \
-X POST \
-H "Authorization: Bearer $HOBBES_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: crm-export-2026-07-23-01" \
--data '{
"campaign": {"name": "Summer outreach"},
"generateThumbnails": true,
"links": [
{
"externalId": "crm-contact-1042",
"firstName": "Ada",
"lastName": "Lovelace",
"email": "ada@example.com",
"phone": "+1 415 555 0100",
"role": "VP of Operations",
"company": "Example Co",
"context": "Interested in automating lead follow-up.",
"shareTitle": "A personalized walkthrough for Example Co",
"shareDescription": "See the workflow we discussed.",
"shareThumbnailUrl": "https://cdn.example.com/share-image.png",
"prospectLogoUrl": "https://cdn.example.com/example-logo.png",
"prospectDomain": "example.com",
"displayName": "Ada at Example Co",
"active": true
}
]
}'
```
`campaign` can identify an existing campaign by id or create/reuse one by name.
The personalization fields match the CSV import contract. `externalId`,
`displayName`, and `active` are API-specific.
`prospectDomain` identifies the prospect and can help logo discovery. It does
not choose the published link's delivery domain. Hobbes publishes through the
organization's active custom domain or configured Sales Agent URL. Creation
returns `409` when neither is configured.
Only provide public HTTP or HTTPS image URLs. Hobbes rejects private-network
targets, unsafe redirects, unsupported content types, and images larger than
10 MB.
## Preserve idempotency
Creation, thumbnail regeneration, and explicit retry operations require an
`Idempotency-Key`. Generate a stable key for one logical operation and keep it
with your integration state.
* Replaying the same key with the same request returns the original job.
* Reusing the key with different content returns `409`.
* An idempotent replay does not consume quota again.
## Poll the job
Creation returns `202 Accepted` with:
* A job summary in the response body
* `Location: /api/v1/custom-link-jobs/{job_id}`
* `Retry-After: 2`
Poll the `Location` every two seconds. After 30 seconds, back off to every five
seconds. Store the response `ETag` and send it on the next request:
```bash theme={null}
curl "https://api-us.hihobbes.com/api/v1/custom-link-jobs/$JOB_ID" \
-H "Authorization: Bearer $HOBBES_API_KEY" \
-H "If-None-Match: $JOB_ETAG"
```
An unchanged job returns `304 Not Modified` without a response body. Terminal
statuses are `completed`, `completed_with_errors`, `cancelled`, and `failed`.
Non-terminal statuses are `queued` and `processing`.
Fetch `GET /api/v1/custom-link-jobs/{job_id}/items` when counters change or the
job becomes terminal. Items remain in input order and independently report:
* `creationStatus` for validation and link creation
* `thumbnailStatus` for requested thumbnail work
* The Custom Link id and published URL when creation succeeds
* Structured validation, creation, or thumbnail errors when work fails
Request-level errors reject the whole request. Item-level validation errors
allow otherwise valid links to proceed, so a terminal job may be
`completed_with_errors`.
## Manage links and campaigns
Use the list and detail endpoints to filter by campaign, status, external id,
email, company, date, or search text. `PATCH /api/v1/custom-links/{id}` updates
personalization, sharing metadata, campaign membership, or active state.
Thumbnail work is queued only when an affected field changes.
Bulk actions can activate, deactivate, or move up to 500 links. Hard deletion
is not exposed. Deactivation preserves historical attribution.
Campaign endpoints create, list, rename, retrieve, and delete organizational
folders. Deleting a campaign unfiles its links without deleting them.
## Read engagement
Every Custom Link list and detail response includes an `engagement` rollup.
The link-level rollup combines all activity associated with that link; it is
not the journey of one person or browser. The lifecycle uses the same
definitions in link and session responses:
| Stage | Definition |
| - | - |
| `opened` | At least one non-bot `widget_loaded` page view |
| `started` | A session recording exists for the link |
| `engaged` | A visitor spoke, typed a message, clicked a suggestion, or continued the experience |
Stages only advance. Lead submission, meeting click, and meeting booking are
reported as conversion flags rather than additional stages. Because they prove
downstream human activity, they also advance a link or session to `engaged` when
an earlier client event was missed. `botScannedOnly` identifies a server-side
link resolution with no observed human open or downstream activity.
Use `GET /api/v1/custom-links/{id}/sessions` to retrieve the sessions associated
with a link. The result intentionally excludes transcripts and visitor PII.
Full session detail still requires `sessions:read`; transcripts require the
separate `transcripts:read` scope.
`loadCount` counts accepted non-bot load events, while `pageViewCount` deduplicates
those events by `pageViewId`. Full-screen opens are recorded independently of
the real-time conversation connection.
`uniqueVisitorCount` is the best available browser-continuity estimate. When
consent and browser storage allow it, Hobbes uses a persistent anonymous browser
identifier. A new browser, device, domain, private window, or cleared storage
may still count separately; the identifier does not identify a person.
Use `visitorCountMode` to interpret the total:
| Mode | Meaning |
| - | - |
| `identified` | Every counted visit had a persistent anonymous browser identifier |
| `estimated` | One or more ephemeral page views contributed because persistent storage was unavailable |
`persistentUniqueVisitorCount` and `ephemeralPageViewCount` remain exact raw
counts in either mode. When the mode is `estimated`, treat
`loadsPerUniqueVisitor` as approximate because Hobbes cannot establish whether
ephemeral page views came from the same returning browser.
Use `GET /api/v1/custom-link-campaigns/{id}/engagement` for raw campaign totals.
A campaign response includes generated, opened, started, engaged, lead,
meeting-click, meeting-booking, bot-only, load, page-view, visitor, and session
counts. It uses the same visitor certainty fields as each link.
UTM attribution is session-level. Retrieve a session with
`GET /api/v1/sessions/{session_id}` and read `tracking.utmSource`,
`tracking.utmCampaign`, `tracking.utmMedium`, `tracking.utmTerm`, and
`tracking.utmContent`. Link and campaign engagement responses do not aggregate
UTM values.
A generated link is not proof that an email was sent, delivered, or not bounced;
join those denominators from the sending platform before calculating upper-
funnel conversion rates.
## Regenerate, cancel, or retry
* `POST /api/v1/custom-links/{id}/thumbnail-jobs` explicitly regenerates one thumbnail.
* `POST /api/v1/custom-link-jobs/{id}/cancel` requests best-effort cancellation of unfinished work.
* `POST /api/v1/custom-link-jobs/{id}/retry` creates a child job for failed or selected items.
Completed work remains available after cancellation. Cancellation does not
refund quota. Explicit thumbnail retries consume new render units; Hobbes'
internal retries do not.
## Plan for limits
The standard per-key limit is 120 HTTP requests per minute. Additional
organization-wide protections apply:
| Limit | Default |
| - | - |
| Creation, thumbnail, and retry requests | 10 per minute |
| Job polling | 300 per minute across the organization, still 120 per key |
| Accepted links | 2,000 per UTC hour and 10,000 per UTC day |
| Thumbnail render units | 2,000 per UTC hour and 10,000 per UTC day |
| Unfinished thumbnail items | 1,000 per organization |
Invalid items do not consume weighted quota. Hobbes validates the whole request
before admission; if all otherwise valid items would exceed a quota, the request
returns `429` rather than accepting an arbitrary partial batch.
On `429`, wait for `Retry-After` and inspect the remaining quota and reset
headers before retrying. A `503` indicates the global queue or worker circuit
breaker is unavailable; no quota is charged for rejected work.
# Data model
Source: https://docs.hihobbes.com/guides/data-model
Understand how sessions, people, accounts, transcripts, and metrics relate.
The read API exposes four levels of derived demo intelligence plus optional raw
conversation turns.
```mermaid theme={null}
flowchart LR
S["Session"] --> P["Person"]
P --> A["Account"]
S --> T["Transcript"]
S --> M["Metrics"]
```
## Sessions
A session is one analyzed production demo. List responses contain the fields
needed for routing and synchronization. Session detail adds timeline events,
topics, objections, qualification reasoning, next steps, and full tracking
context.
Use the stable session UUID as your external-system idempotency key. `displayId`
is intended for humans and may be absent.
## People
A person represents a prospect aggregated across sessions. Hobbes identifies
people by normalized email and exposes their first and last activity, total
time, latest qualification, latest intent, and rolling summary.
Person records can evolve after later sessions. Treat them as current profiles,
not immutable events.
## Accounts
An account rolls people up by registrable business email domain. It includes
user, session, booking, qualification, high-intent, duration, and recency
aggregates.
Consumer email domains may not produce useful B2B accounts. Use person and
session records when a business domain is unavailable.
## Metrics
Metrics aggregate analyzed sessions over a trailing 1-365 day window. Counts
and rates are recalculated for each request. Use them for operational dashboards,
not as a substitute for storing session-level history.
## Null and empty values
* A `null` field means Hobbes did not capture or derive that value.
* An empty array means analysis completed but produced no items of that type.
* A missing resource returns `404`; it is not represented as `null`.
* New response fields may appear within v1. Ignore fields your integration does
not recognize.
# Errors, rate limits, and retries
Source: https://docs.hihobbes.com/guides/errors-rate-limits
Handle failures without dropping data or creating retry storms.
Hobbes returns JSON errors with a `detail` field and attaches `X-Request-ID`
to successful and failed requests. Authentication, authorization, missing
resource, rate-limit, and server errors use a string:
```json theme={null}
{
"detail": "Insufficient scope"
}
```
Validation errors use an array so each invalid path or query parameter can be
identified separately:
```json theme={null}
{
"detail": [
{
"type": "less_than_equal",
"loc": ["query", "limit"],
"msg": "Input should be less than or equal to 200",
"input": "201"
}
]
}
```
## Status codes
| Status | Meaning | Retry? |
| - | - | - |
| `200` | Request succeeded | No |
| `202` | Asynchronous job accepted | Poll the job URL |
| `304` | Polled job is unchanged | Continue after the polling interval |
| `401` | Key missing or invalid | No, replace or fix the key |
| `403` | Required scope missing | No, create a correctly scoped key |
| `404` | Resource unavailable to this organization | No |
| `409` | Idempotency key conflict or delivery URL unavailable | No, correct the request |
| `422` | Path or query parameter failed validation | No, fix the request |
| `429` | Request, transcript, Custom Link, render, or organization queue quota exceeded | Yes, after `Retry-After` |
| `503` | Global queue or worker circuit breaker unavailable | Yes, after `Retry-After` |
| `5xx` | Temporary server failure | Yes, with exponential backoff |
## Rate limits
Keys allow 120 requests per 60-second window by default. Hobbes may configure a
different limit for a specific key.
Custom Link creation, thumbnail, and retry operations also allow 10 requests per
minute per organization. Job polling allows 300 per minute per organization
while retaining the lower 120-per-key limit. Creation and thumbnail compute have
separate weighted hourly and daily quotas; see [Create Custom Links](/guides/custom-links).
```text theme={null}
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 117
```
On `429`, sleep for the number of seconds in `Retry-After`. Add jitter if many
workers share the same key.
```python theme={null}
import random
import time
if response.status_code == 429:
retry_after = int(response.headers.get("Retry-After", "30"))
time.sleep(retry_after + random.random())
```
For `5xx` and network failures, retry a bounded number of times with exponential
backoff. Do not retry authentication, authorization, validation, or missing
resource errors.
## Support diagnostics
Log these values for every failed request:
* HTTP method and path, excluding secret query data
* Response status and `detail`
* `X-Request-ID`
* Attempt number and next retry time
Never log the `Authorization` or `x-api-key` header.
# Pagination and filtering
Source: https://docs.hihobbes.com/guides/pagination-filtering
Build complete, efficient, and restartable reads.
List endpoints use offset pagination. They default to 50 records and accept a
maximum `limit` of 200.
```json theme={null}
{
"pagination": {
"total": 248,
"limit": 200,
"offset": 0
}
}
```
Request the next page while `offset + limit < total`. The maximum accepted
offset is 1,000,000.
## Read every page
```python Python theme={null}
import os
import requests
base_url = "https://api-us.hihobbes.com/api/v1/sessions"
headers = {"Authorization": f"Bearer {os.environ['HOBBES_API_KEY']}"}
offset = 0
while True:
response = requests.get(
base_url,
headers=headers,
params={"limit": 200, "offset": offset},
timeout=30,
)
response.raise_for_status()
payload = response.json()
for session in payload["sessions"]:
process(session)
page = payload["pagination"]
offset += page["limit"]
if offset >= page["total"]:
break
```
```typescript TypeScript theme={null}
const endpoint = "https://api-us.hihobbes.com/api/v1/sessions";
let offset = 0;
while (true) {
const url = new URL(endpoint);
url.searchParams.set("limit", "200");
url.searchParams.set("offset", String(offset));
const response = await fetch(url, {
headers: { Authorization: `Bearer ${process.env.HOBBES_API_KEY}` },
});
if (!response.ok) throw new Error(await response.text());
const payload = await response.json();
for (const session of payload.sessions) await processSession(session);
offset += payload.pagination.limit;
if (offset >= payload.pagination.total) break;
}
```
## Filters
Session and people filters can be combined. Status filters accept comma-separated
values, such as `buying_intent=high,medium`.
| Filter | Sessions | People | Behavior |
| - | - | - | - |
| `date_from`, `date_to` | Yes | Yes | Session start time or person last-seen time, ISO 8601 |
| `qualification_status` | Yes | Yes | `qualified`, `unqualified`, `unknown` |
| `buying_intent` | Yes | Yes | `high`, `medium`, `low`, `none` |
| `booked_status` | Yes | No | `booked`, `not_booked` |
| `search` | Email | Email | Case-insensitive partial match |
Account `search` performs a partial domain match. Metrics use a trailing `days`
window instead of date boundaries.
Offset pagination is stable enough for bounded backfills, but records can be
added while a long export runs. For recurring exports, use an overlapping
`date_from` watermark and upsert by stable resource id.
# Update the Playbook and publish an agent
Source: https://docs.hihobbes.com/guides/playbook-agent-api
Preview Playbook changes in staging and publish the exact approved agent version.
Use the Hobbes API when a backend service or coding agent needs to read or
update the Playbook. Updates always go to staging first. Publishing production
is a separate action with its own scope, confirmation, and test gate.
For a person working from Claude or another AI client, connect to the
[Hobbes MCP server](/guides/connect-ai-clients) instead of managing an API key.
## Choose scopes
| Scope | Use it for |
| - | - |
| `playbook:read` | Read staging and production Playbooks, version details, links, and ready suggestions |
| `playbook:write` | Preview authored changes and apply approved previews or stored suggestions to staging |
| `agent:publish` | Queue the exact current staging version for production after explicit confirmation and tests |
These scopes are off by default and are never added to existing keys. Create or
rotate a key with only the access the integration needs.
## Preview and apply a change
Call `GET /api/v1/playbook`. Save `sectionsEtag` and use the returned
section catalog to target supported fields. The response also includes
links for testing the staging and production agents.
Call `POST /api/v1/playbook/update-previews` with restricted JSON Patch
operations and a stable `operationKey`. Set `expectedSectionsEtag` to the
current `sectionsEtag`.
Hobbes validates the request against a clone and returns a before-and-after
summary without changing staging.
Show the changed sections to the person who requested the update. Do not
treat a preview as an applied or published change.
Call `POST /api/v1/playbook/update-previews/{preview_id}/apply`. The preview
must be unexpired and created by the same API key. If staging changed after
the preview, Hobbes returns `409` and creates no version. Create a fresh
preview against the latest `sectionsEtag`.
Open the staging link from Hobbes and verify the changed behavior before
publishing.
Previews expire after 24 hours. Repeating a successful apply returns the
original result instead of creating another version.
## Apply a Hobbes suggestion
Call `GET /api/v1/playbook/suggestions` to list ready suggestion groups with
their evidence and exact proposed changes. Apply one with
`POST /api/v1/playbook/suggestions/{group_id}/apply` only when the stored wording
should be used as generated. Use the preview process when the wording needs to
change.
## Publish the staged agent
Publishing changes production and requires a new confirmation at the time of
the request.
1. Read the Playbook again and confirm the exact current staging version.
2. Ask the user to confirm publishing that version to production.
3. Call `POST /api/v1/agent/publish-jobs` with a stable `operationKey`, the
current staging version, and `confirmation: "publish_to_production"`.
4. Poll `GET /api/v1/agent/publish-jobs/{job_id}`. Send the returned `ETag` as
`If-None-Match` and honor `Retry-After`.
Hobbes runs its conversation tests before changing production. A failed job
does not publish the agent. Review its safe failure message, correct staging,
and ask for confirmation again before creating a different publish job.
Never infer publishing approval from an earlier Playbook request. The user must
confirm the exact staged version immediately before the publish job is queued.
# Transcript access and security
Source: https://docs.hihobbes.com/guides/transcripts-security
Retrieve raw conversation text selectively and handle it as sensitive data.
Transcripts require the separate `transcripts:read` scope. The scope is off by
default because raw conversation text can contain prospect PII and because
transcript reads have a separate organization quota.
## Quota behavior
* 2,000 successful transcript reads per organization per UTC day
* Shared across all keys in the organization
* Charged only after Hobbes confirms the session belongs to the organization
* Resets at 00:00 UTC
* Returns `429` with `Retry-After` when exhausted
Malformed session ids and `404` responses do not consume quota.
## Prefer derived fields
Session detail already includes summaries, qualification, topics, objections,
timeline milestones, and next steps. Use those fields for routing and analytics.
Fetch raw transcripts only when the integration needs the original conversation.
## Security checklist
* Use a dedicated key with the minimum required scopes.
* Keep transcript processing server-side.
* Encrypt transcript data in transit and at rest.
* Apply the same access and retention rules used for call recordings and CRM notes.
* Avoid bulk transcript backfills unless the use case requires them.
* Never send transcripts to another processor without confirming your data policy.
The API reference shows copyable examples only. It intentionally does not
execute requests in the documentation browser or proxy API keys through the
docs provider.
# Versioning and compatibility
Source: https://docs.hihobbes.com/guides/versioning
Build integrations that remain stable as the Hobbes API evolves.
The current API version is `v1` and appears in every endpoint path.
```text theme={null}
https://api-us.hihobbes.com/api/v1
```
## v1 compatibility policy
Within v1, Hobbes may:
* Add response fields
* Add enum-like string values
* Add optional query parameters
* Add endpoints
* Improve descriptions and examples
Within v1, Hobbes will not remove or rename existing fields or change their
meaning without a migration path.
## Build defensively
* Ignore response fields your integration does not recognize.
* Treat documented status values as open string sets unless the schema marks
them as closed enums.
* Handle nullable fields explicitly.
* Use resource ids for idempotent upserts.
* Pin business logic to the values you need instead of rejecting the entire
response when a new value appears.
## OpenAPI snapshot
The API reference is generated from a reviewed OpenAPI snapshot. The live
engineering schema remains available at:
```text theme={null}
https://api-us.hihobbes.com/api/v1/openapi.json
```
The public documentation snapshot is refreshed and reviewed whenever the
external contract changes.
# Quickstart
Source: https://docs.hihobbes.com/quickstart
Create a key and retrieve recent qualified sessions in five minutes.
In Hobbes, open **Settings → Organization → API keys**. Create a key with
the **Sessions** scope. Only organization admins can create or revoke keys.
Copy the token when it appears. Hobbes shows the plaintext token once and
stores only its hash.
Keep the token in a secret manager or environment variable. Never commit it
to source control or expose it in browser code.
```bash theme={null}
export HOBBES_API_KEY="hb_live_..."
```
Request the ten most recent sessions whose latest qualification result is
`qualified`.
```bash cURL theme={null}
curl --fail-with-body \
--get "https://api-us.hihobbes.com/api/v1/sessions" \
--data-urlencode "qualification_status=qualified" \
--data-urlencode "limit=10" \
--header "Authorization: Bearer $HOBBES_API_KEY"
```
```python Python theme={null}
import os
import requests
response = requests.get(
"https://api-us.hihobbes.com/api/v1/sessions",
headers={"Authorization": f"Bearer {os.environ['HOBBES_API_KEY']}"},
params={"qualification_status": "qualified", "limit": 10},
timeout=30,
)
response.raise_for_status()
payload = response.json()
for session in payload["sessions"]:
print(session["id"], session["email"], session["buyingIntent"])
```
```typescript TypeScript theme={null}
const url = new URL("https://api-us.hihobbes.com/api/v1/sessions");
url.searchParams.set("qualification_status", "qualified");
url.searchParams.set("limit", "10");
const response = await fetch(url, {
headers: { Authorization: `Bearer ${process.env.HOBBES_API_KEY}` },
});
if (!response.ok) {
throw new Error(`Hobbes API ${response.status}: ${await response.text()}`);
}
const payload = await response.json();
for (const session of payload.sessions) {
console.log(session.id, session.email, session.buyingIntent);
}
```
List responses include the current `limit`, `offset`, and total matching
records. Request the next page while `offset + limit < total`.
```json theme={null}
{
"pagination": {
"total": 248,
"limit": 10,
"offset": 0
}
}
```
Save the `X-Request-ID` response header in integration logs. It identifies the
exact request if you need help diagnosing a failure.
## Next steps
Create narrowly scoped keys and rotate them safely.
Build complete and restartable data synchronization jobs.
# Build account engagement rollups
Source: https://docs.hihobbes.com/recipes/account-engagement-rollups
Prioritize companies using people, session, booking, and intent aggregates.
Account rollups group people by registrable business email domain. They are
useful for account-based routing and prioritization.
```bash cURL theme={null}
curl --fail-with-body --get \
"https://api-us.hihobbes.com/api/v1/accounts" \
--data-urlencode "limit=200" \
--header "Authorization: Bearer $HOBBES_API_KEY"
```
```python Python theme={null}
import os
import requests
response = requests.get(
"https://api-us.hihobbes.com/api/v1/accounts",
headers={"Authorization": f"Bearer {os.environ['HOBBES_API_KEY']}"},
params={"limit": 200},
timeout=30,
)
response.raise_for_status()
accounts = response.json()["accounts"]
ranked = sorted(
accounts,
key=lambda account: (
account["qualifiedUsers"] or 0,
account["highIntentUsers"] or 0,
account["lastSeenAt"] or "",
),
reverse=True,
)
for account in ranked:
print(account["accountDomain"], account["qualifiedUsers"], account["totalSessions"])
```
```typescript TypeScript theme={null}
const response = await fetch("https://api-us.hihobbes.com/api/v1/accounts?limit=200", {
headers: { Authorization: `Bearer ${process.env.HOBBES_API_KEY}` },
});
if (!response.ok) throw new Error(await response.text());
const { accounts } = await response.json();
accounts.sort((a, b) =>
(b.qualifiedUsers ?? 0) - (a.qualifiedUsers ?? 0) ||
(b.highIntentUsers ?? 0) - (a.highIntentUsers ?? 0) ||
String(b.lastSeenAt ?? "").localeCompare(String(a.lastSeenAt ?? "")),
);
console.table(accounts);
```
Retrieve `/accounts/{domain}` when an account workflow starts from a known
domain. URL-encode the domain before adding it to the path.
# Find high-intent prospects
Source: https://docs.hihobbes.com/recipes/find-high-intent-prospects
Identify recently active people with high buying intent.
The people endpoint combines activity across sessions. Use it when outreach or
routing should operate on the latest prospect profile rather than one demo.
```bash cURL theme={null}
curl --fail-with-body --get \
"https://api-us.hihobbes.com/api/v1/people" \
--data-urlencode "buying_intent=high" \
--data-urlencode "qualification_status=qualified" \
--data-urlencode "date_from=2026-07-01T00:00:00Z" \
--data-urlencode "limit=200" \
--header "Authorization: Bearer $HOBBES_API_KEY"
```
```python Python theme={null}
import os
import requests
response = requests.get(
"https://api-us.hihobbes.com/api/v1/people",
headers={"Authorization": f"Bearer {os.environ['HOBBES_API_KEY']}"},
params={
"buying_intent": "high",
"qualification_status": "qualified",
"date_from": "2026-07-01T00:00:00Z",
"limit": 200,
},
timeout=30,
)
response.raise_for_status()
for person in response.json()["people"]:
print(person["email"], person["totalSessions"], person["summaryMarkdown"])
```
```typescript TypeScript theme={null}
const url = new URL("https://api-us.hihobbes.com/api/v1/people");
url.searchParams.set("buying_intent", "high");
url.searchParams.set("qualification_status", "qualified");
url.searchParams.set("date_from", "2026-07-01T00:00:00Z");
url.searchParams.set("limit", "200");
const response = await fetch(url, {
headers: { Authorization: `Bearer ${process.env.HOBBES_API_KEY}` },
});
if (!response.ok) throw new Error(await response.text());
const { people } = await response.json();
console.table(people.map(({ email, totalSessions, summaryMarkdown }) => ({
email,
totalSessions,
summaryMarkdown,
})));
```
Upsert by person `id`. Email is the retrieval key for a single person, but the
stable UUID is the safer external-system identity.
# Build a funnel dashboard
Source: https://docs.hihobbes.com/recipes/funnel-dashboard
Read qualification, booking, intent, duration, and source metrics.
The metrics endpoint returns one aggregate snapshot for a trailing 1-365 day
window. Poll it on your dashboard's refresh cadence rather than once per visitor.
```bash cURL theme={null}
curl --fail-with-body --get \
"https://api-us.hihobbes.com/api/v1/metrics" \
--data-urlencode "days=30" \
--header "Authorization: Bearer $HOBBES_API_KEY"
```
```python Python theme={null}
import os
import requests
response = requests.get(
"https://api-us.hihobbes.com/api/v1/metrics",
headers={"Authorization": f"Bearer {os.environ['HOBBES_API_KEY']}"},
params={"days": 30},
timeout=30,
)
response.raise_for_status()
metrics = response.json()
print({
"sessions": metrics["totalSessions"],
"qualified": metrics["qualifiedCount"],
"booked": metrics["bookedCount"],
"qualification_rate": metrics["qualificationRate"],
})
```
```typescript TypeScript theme={null}
const response = await fetch("https://api-us.hihobbes.com/api/v1/metrics?days=30", {
headers: { Authorization: `Bearer ${process.env.HOBBES_API_KEY}` },
});
if (!response.ok) throw new Error(await response.text());
const metrics = await response.json();
console.log({
sessions: metrics.totalSessions,
qualified: metrics.qualifiedCount,
booked: metrics.bookedCount,
qualificationRate: metrics.qualificationRate,
topSources: metrics.topSources,
});
```
`qualificationRate` is already a percentage from 0 to 100. Format it with a
percent sign without multiplying it again. Use session exports when you need
custom cohorts or date boundaries rather than a trailing-day window.
# Export sessions to a warehouse
Source: https://docs.hihobbes.com/recipes/incremental-warehouse-export
Build a restartable incremental export with overlapping watermarks.
Use a high-water mark plus a short overlap. Offset pagination handles each
bounded window, while upserts by session UUID make reruns safe.
```bash cURL theme={null}
curl --fail-with-body --get \
"https://api-us.hihobbes.com/api/v1/sessions" \
--data-urlencode "date_from=2026-07-01T00:00:00Z" \
--data-urlencode "date_to=2026-07-11T00:00:00Z" \
--data-urlencode "limit=200" \
--data-urlencode "offset=0" \
--header "Authorization: Bearer $HOBBES_API_KEY"
```
```python Python theme={null}
import json
import os
import requests
endpoint = "https://api-us.hihobbes.com/api/v1/sessions"
headers = {"Authorization": f"Bearer {os.environ['HOBBES_API_KEY']}"}
offset = 0
with open("hobbes-sessions.ndjson", "w", encoding="utf-8") as output:
while True:
response = requests.get(
endpoint,
headers=headers,
params={
"date_from": "2026-07-01T00:00:00Z",
"date_to": "2026-07-11T00:00:00Z",
"limit": 200,
"offset": offset,
},
timeout=30,
)
response.raise_for_status()
payload = response.json()
for session in payload["sessions"]:
output.write(json.dumps(session) + "\n")
offset += payload["pagination"]["limit"]
if offset >= payload["pagination"]["total"]:
break
```
```typescript TypeScript theme={null}
import { appendFile } from "node:fs/promises";
let offset = 0;
while (true) {
const url = new URL("https://api-us.hihobbes.com/api/v1/sessions");
url.searchParams.set("date_from", "2026-07-01T00:00:00Z");
url.searchParams.set("date_to", "2026-07-11T00:00:00Z");
url.searchParams.set("limit", "200");
url.searchParams.set("offset", String(offset));
const response = await fetch(url, {
headers: { Authorization: `Bearer ${process.env.HOBBES_API_KEY}` },
});
if (!response.ok) throw new Error(await response.text());
const payload = await response.json();
const ndjson = payload.sessions.map((session) => JSON.stringify(session)).join("\n");
if (ndjson) await appendFile("hobbes-sessions.ndjson", `${ndjson}\n`);
offset += payload.pagination.limit;
if (offset >= payload.pagination.total) break;
}
```
Store raw session-list rows first. Enrich selected records with session detail
in a separate step so a detail failure does not force the full list export to restart.
# Retrieve transcripts safely
Source: https://docs.hihobbes.com/recipes/retrieve-transcripts
Fetch ordered conversation turns only for sessions that need raw text.
Start from a filtered session list, then fetch transcripts only for selected
session UUIDs. This keeps PII exposure and quota use bounded.
```bash cURL theme={null}
SESSION_ID="018f3f6a-0d7b-7f56-bb2a-54c91e57a202"
curl --fail-with-body \
"https://api-us.hihobbes.com/api/v1/sessions/$SESSION_ID/transcript" \
--header "Authorization: Bearer $HOBBES_API_KEY"
```
```python Python theme={null}
import os
import requests
session_id = "018f3f6a-0d7b-7f56-bb2a-54c91e57a202"
response = requests.get(
f"https://api-us.hihobbes.com/api/v1/sessions/{session_id}/transcript",
headers={"Authorization": f"Bearer {os.environ['HOBBES_API_KEY']}"},
timeout=30,
)
if response.status_code == 429:
raise RuntimeError(f"Retry after {response.headers['Retry-After']} seconds")
response.raise_for_status()
for turn in response.json()["entries"]:
print(f"{turn['sequenceNumber']:>3} {turn['speaker']}: {turn['text']}")
```
```typescript TypeScript theme={null}
const sessionId = "018f3f6a-0d7b-7f56-bb2a-54c91e57a202";
const response = await fetch(
`https://api-us.hihobbes.com/api/v1/sessions/${sessionId}/transcript`,
{ headers: { Authorization: `Bearer ${process.env.HOBBES_API_KEY}` } },
);
if (response.status === 429) {
throw new Error(`Retry after ${response.headers.get("Retry-After")} seconds`);
}
if (!response.ok) throw new Error(await response.text());
const transcript = await response.json();
for (const turn of transcript.entries) {
console.log(`${turn.sequenceNumber} ${turn.speaker}: ${turn.text}`);
}
```
Transcript access requires `transcripts:read`, is limited to 2,000 successful
reads per organization per UTC day, and can expose prospect PII.
# Sync qualified sessions to a CRM
Source: https://docs.hihobbes.com/recipes/sync-qualified-sessions
Pull recent qualified demos and produce idempotent CRM records.
Use the session UUID as the external id in your CRM. Query a short overlapping
time window on each run, then upsert rather than insert. The overlap protects
against delayed analysis and interrupted jobs.
## Request recent qualified sessions
```bash cURL theme={null}
curl --fail-with-body --get \
"https://api-us.hihobbes.com/api/v1/sessions" \
--data-urlencode "date_from=2026-07-09T00:00:00Z" \
--data-urlencode "qualification_status=qualified" \
--data-urlencode "buying_intent=high,medium" \
--data-urlencode "limit=200" \
--header "Authorization: Bearer $HOBBES_API_KEY"
```
```python Python theme={null}
import os
import requests
response = requests.get(
"https://api-us.hihobbes.com/api/v1/sessions",
headers={"Authorization": f"Bearer {os.environ['HOBBES_API_KEY']}"},
params={
"date_from": "2026-07-09T00:00:00Z",
"qualification_status": "qualified",
"buying_intent": "high,medium",
"limit": 200,
},
timeout=30,
)
response.raise_for_status()
crm_records = [
{
"external_id": session["id"],
"email": session["email"],
"name": session["name"],
"company": session["business"],
"buying_intent": session["buyingIntent"],
"summary": session["summaryMarkdown"],
"last_demo_at": session["startTime"],
}
for session in response.json()["sessions"]
if session["email"]
]
print(crm_records)
```
```typescript TypeScript theme={null}
const url = new URL("https://api-us.hihobbes.com/api/v1/sessions");
url.searchParams.set("date_from", "2026-07-09T00:00:00Z");
url.searchParams.set("qualification_status", "qualified");
url.searchParams.set("buying_intent", "high,medium");
url.searchParams.set("limit", "200");
const response = await fetch(url, {
headers: { Authorization: `Bearer ${process.env.HOBBES_API_KEY}` },
});
if (!response.ok) throw new Error(await response.text());
const { sessions } = await response.json();
const crmRecords = sessions.filter((session) => session.email).map((session) => ({
externalId: session.id,
email: session.email,
name: session.name,
company: session.business,
buyingIntent: session.buyingIntent,
summary: session.summaryMarkdown,
lastDemoAt: session.startTime,
}));
console.log(crmRecords);
```
## Production pattern
1. Store the last successful session timestamp.
2. Subtract at least one hour to create the next `date_from` watermark.
3. Read every page.
4. Upsert by session UUID.
5. Advance the watermark only after every page succeeds.
Retrieve [session detail](/api-reference/get-session) only when the CRM needs
topics, objections, timeline events, or next steps.
# Track demo conversions
Source: https://docs.hihobbes.com/recipes/track-demo-conversions
Send session duration, email category, and buying-intent signals to your analytics and advertising tools.
Use browser events for live elapsed-time and accepted-email signals. Use the
existing `session.completed` webhook for final buying intent, including when
analysis finishes after the visitor closes the page. Hobbes emits the signals;
your GTM tags or webhook receiver submit conversions to your ad account.
## Browser contract
The existing `window.dataLayer.push` and `hobbes:event` CustomEvent carry:
| Event | Additional fields | When |
| - | - | - |
| `hobbes_email_classified` | `hobbes_email_domain_type` | The backend accepts the call-start request and returns its email-check result. |
| `hobbes_session_duration_threshold` | `hobbes_duration_threshold_seconds` (60, 300, 600), `hobbes_session_elapsed_seconds` | Once for each crossed threshold in a live demo. |
All subsequent session events also include `hobbes_email_domain_type` and
`hobbes_session_recording_id` when available. `hobbes_session_id` remains the
voice call ID for compatibility. Join to webhook `session.id` using
`hobbes_session_recording_id`, not the call ID. The organization, widget session,
surface, client timestamp, and existing first-touch attribution fields remain.
If a recording ID is absent, use a single delivery route for that conversion
signal. Cross-route deduplication requires the recording ID.
Categories are `personal`, `corporate`, `disposable`, and `unknown`. Corporate
means a company provider/domain type, not a qualified buyer. Rejected emails do
not emit a classification event. The current call-start policy rejects disposable
email; consumers should nevertheless accept that category in the contract.
Missing email, classification timeout, malformed/unknown result, and older sessions
are `unknown`. There is no additional classifier request or lookup. The new
browser fields contain no email address or email domain.
```js theme={null}
{
event: 'hobbes_session_duration_threshold',
hobbes_event: 'hobbes_session_duration_threshold',
hobbes_surface: 'full_page',
hobbes_organization_id: 'organization-uuid',
hobbes_session_id: 'voice-call-uuid',
hobbes_session_recording_id: 'recording-uuid',
hobbes_email_domain_type: 'corporate',
hobbes_duration_threshold_seconds: 300,
hobbes_session_elapsed_seconds: 300,
hobbes_gclid: 'captured-click-id',
hobbes_client_timestamp: '2026-09-10T12:05:00.000Z'
}
```
Duration begins with `hobbes_session_started`: the accepted demo is ready and its
startup/research overlay has closed. Page load, launcher opening, lead submission,
and company research do not run this clock. Listening, mute, quiet gaps, and time
in a background tab count. A disconnected transport pauses emission; reconnection
with the same call ID catches up crossed thresholds using the original clock.
Explicit end, idle/system timeout, or terminal connection closure ends the clock.
Timer throttling may delay a push; elapsed seconds can exceed its threshold.
Re-renders and surface changes do not restart it. A new call starts a new set.
Unmount/page closure ends browser delivery; no intent polling or return visit is required.
The existing webhook `session.duration_seconds` remains recording wall time
(`end_time - start_time`). It can include backend startup and earlier chat in a
recording reused for a demo, so it is not numerically interchangeable with the
ready-demo browser clock. Choose and name a duration definition for each
conversion action; use one route consistently. Do not interpret either as active
speaking time or verified attention.
## GTM setup
1. Load your GTM container on the same document as the widget. For a
hosted standalone demo, use its configured container. A browser data layer is
document-local; an unrelated parent page does not automatically receive it.
2. Add Data Layer Variables for `hobbes_duration_threshold_seconds`,
`hobbes_email_domain_type`, `hobbes_session_recording_id`, and
`hobbes_organization_id`.
3. Add a Custom Event trigger named exactly
`hobbes_session_duration_threshold`. Create one trigger per desired threshold,
with the numeric variable equal to 60, 300, or 600. Optionally require email
type to equal `corporate`.
4. For company-email conversions, use Custom Event `hobbes_email_classified`
with `hobbes_email_domain_type` equal to `corporate`.
5. Attach the relevant conversion tag and configure consent through the existing
CMP/GTM consent setup. A data-layer event is not consent to send advertising
data. Preview in Tag Assistant before publishing your container.
Example conversion identity: `organization-uuid:recording-uuid:demo_ready_300s`.
Use a distinct definition for corporate-only milestones, such as
`corporate_demo_ready_300s`. Supply the same identity to your receiver if both
sources are involved. Do not make separate browser and offline conversion actions
for the same logical milestone and assume Google will deduplicate across them.
See [Google's data-layer guide](https://developers.google.com/tag-platform/tag-manager/datalayer).
## Completion webhook contract
Configure an enabled organization webhook with both `notify_on_active_session`
and `notify_on_inactive_session` enabled. Those cover eligible analyzed sessions
regardless of booking or qualification; enabling only booked/qualified filters
would omit the mid-funnel sessions this integration needs. Existing internal,
staging-preview, and unclaimed website-chat exclusions still apply.
The existing payload retains transcript, sales summary, contact/consent, and
tracking fields. This abbreviated example shows the conversion fields:
```json theme={null}
{
"event": "session.completed",
"idempotency_key": "session.completed:organization-uuid:recording-uuid",
"timestamp": "2026-09-10T12:12:01+00:00",
"session": {
"id": "recording-uuid",
"organization_id": "organization-uuid",
"email_domain_type": "corporate",
"start_time": "2026-09-10T12:00:00+00:00",
"end_time": "2026-09-10T12:10:30+00:00",
"analysis_completed_at": "2026-09-10T12:12:00+00:00",
"duration_seconds": 630,
"tracking": { "gclid": "captured-click-id", "utm_source": "google" }
},
"sales_summary": { "buying_intent": "high" },
"person": { "overall_intent": "medium" }
}
```
`buying_intent` is this session's persisted analysis, not the person's aggregate.
Low, medium, and high are delivered; the receiver chooses its target levels.
Incomplete/failed analysis does not send `session.completed`. A missing intent is
not synthesized as low; skip it for scored conversions. Historical email category
and analysis timestamp may be unknown/null. `webhook.test` is a connectivity test,
not a conversion.
Use `session.end_time` for a conversion defined as "completed high-intent demo".
Use `analysis_completed_at` only if the chosen definition is "analysis became
available". Never use the receiver clock or top-level emission timestamp as a
replacement. A recording-duration threshold can use `start_time + threshold`
when start/end and duration support that threshold. Do not use that timestamp for
a ready-demo threshold with a different clock origin.
The logical event key is also sent in `Idempotency-Key`. Retries preserve it,
the body, and signature; rebuilding delivery for the same recording retains the
logical key. Existing bounded retries and delivery diagnostics are unchanged.
## Receiver and Google mapping
Verify `X-Webhook-Signature: sha256=` over the **raw request body** using
HMAC-SHA256 and the configured webhook secret, with a timing-safe comparison.
Validate the expected organization. Ignore events other than `session.completed`.
For example, select `sales_summary.buying_intent === 'high'`, optionally require
`session.email_domain_type === 'corporate'`, and choose a named definition such as
`completed_high_intent_v1`.
Claim a durable unique key `(organization_id, session.id, conversion_definition)`
in the same database transaction that queues the outbound conversion. Return 2xx
only after that transaction commits. An outbox worker can retry Google delivery
without losing the conversion if the process stops. A duplicate webhook should
acknowledge the existing item; do not mark an item delivered before Google accepts
it. An in-memory set alone is insufficient in a deployed receiver.
A minimal transformation after signature, organization, consent, and dedup checks:
```js theme={null}
function toGoogleEvent(payload, conversionKey) {
if (payload.event !== 'session.completed') return null;
if (payload.sales_summary?.buying_intent !== 'high') return null;
const session = payload.session;
if (!session?.tracking?.gclid || !session.end_time) return null;
return {
eventSource: 'WEB',
eventTimestamp: session.end_time,
transactionId: conversionKey,
adIdentifiers: { gclid: session.tracking.gclid }
};
}
```
For Data Manager, wrap that event in an ingestion request with a Google Ads
operating account and your offline conversion action as
`productDestinationId`. Add only the conversion value/currency you have
defined. Authentication, consent fields, account permissions, ingestion errors,
and diagnostics belong to your existing Google integration. Follow
[Google's event ingestion guide](https://developers.google.com/data-manager/api/devguides/events/send-events)
for the current request schema and destination setup.
Missing click IDs must remain missing and be reported as unmatched/skipped for
this click-based recipe. UTMs, a corporate email category, or a raw email address
are not a GCLID. This work does not introduce enhanced-conversion identifiers or
new Google consent collection. Existing Hobbes consent-aware first-touch storage
and verified cross-domain handoff are retained.