# 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.
# 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.
# 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 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 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 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.
# 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.
## 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 session intelligence, Custom Links, 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, or
create personalized Custom Links in batches without relying on CSV imports.
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.
## 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` |
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 Read API skill so coding agents can build safer integrations.
The Hobbes Read API skill gives AI coding agents a reviewed workflow for reading
sessions, people, accounts, transcripts, and funnel metrics. It includes the
exact endpoint map, scope requirements, pagination rules, retry behavior, and
transcript safeguards.
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 should show `hobbes-read-api`. 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."
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 add write operations.
## 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 |
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.
Custom Links scopes are not added to existing keys automatically. Create or
rotate to a key that explicitly carries the minimum required scope.
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.
# Connect AI clients with MCP
Source: https://docs.hihobbes.com/guides/connect-ai-clients
Give Claude and other AI tools live, permission-scoped access to your Hobbes data — no API keys, no code.
## 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 — Claude, Claude Code, or any tool that supports remote MCP servers — and it can query your sessions, prospects, accounts, transcripts, and funnel metrics, and create Custom Links, using the same data the Hobbes API serves.
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 read, review the permissions, and click **Approve**. Members can grant read access; creating Custom Links can only be granted by an organization admin.
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.
| 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 |
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.
## Creating Custom Links
`custom_links:write` is the one tool that changes data, and it is held to a higher bar:
* 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.
If you want a connection that can never write, simply leave the box unchecked at consent — read permissions are independent.
## 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 at consent | `custom_links:write` scope on the key |
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.
# 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.