Owlbound API

Build on the Owlbound platform. Access contacts, intent signals, AI scoring, data enrichment, and company intelligence through a RESTful API. All endpoints are served under /api/v1 and return JSON.

Base URL

https://app.owlbound.ai/api/v1

Content Type

Content-Type: application/json

Authentication

All API requests require a valid API key. Create and manage keys from the Developer tab in your Owlbound workspace.

Methods

1

X-API-Key headerrecommended

X-API-Key: gtm_sk_...
2

Bearer token

Authorization: Bearer gtm_sk_...

Key types

TypePrefixUse case
Secretgtm_sk_Server-side only. All scopes configurable.
Publishablegtm_pk_Client-safe. Limited to signals:write.

Example Request

curl https://app.owlbound.ai/api/v1/me \
 -H "X-API-Key: gtm_sk_your_key_here"

Scopes

Scopes control which resources a key can access. Secret keys can be configured with any combination. Publishable keys are restricted to signals:write only.

ScopeDescription
intelligence:readAI-powered lead scoring and website analysis
enrichment:readContact and company data lookups
enrichment:writeTrigger enrichment jobs
messages:readRead LinkedIn and email message threads
signals:readRead intent signals
signals:writeIngest intent signals from external sources
contacts:readRead contact records and metadata
contacts:writeCreate and update contact records
sequences:readRead outreach sequences
sequences:writeEnroll contacts into sequences
workflows:readRead signal workflows
workflows:writeTrigger signal workflows
connectors:readRead connector health status
connectors:writeManage connector instances

Default Scopes by Key Type

// Secret keys include all scopes by default
{
 "scopes": [
 "intelligence:read",
 "enrichment:read",
 "enrichment:write",
 "messages:read",
 "signals:read",
 "signals:write",
 "contacts:read",
 "contacts:write",
 "sequences:read",
 "sequences:write",
 "workflows:read",
 "workflows:write",
 "connectors:read",
 "connectors:write"
 ]
}

Rate Limits

Rate limits are applied per API key using a sliding window. When exceeded, the API returns 429 Too Many Requests with a Retry-After header (in seconds).

Plan/ min/ hour/ day
Starter601,00010,000
Pro1205,00050,000
Enterprise30015,000Unlimited

Rate Limit Headers

HTTP/1.1 200 OK
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 58
X-RateLimit-Reset: 1705312200

Capabilities & Credits

Use the capabilities endpoint to see each public API action, its required scope, and the credit cost recorded for successful calls. These successful calls are also mirrored into the workspace usage ledger with an api.* capability ID.

EndpointScopeCredits
POST /contactscontacts:write1
POST /workflows/:id/triggerworkflows:write2
POST /sequences/:id/enrollsequences:write3
POST /contacts/:id/enrichenrichment:write5

Capability inventory

curl https://app.owlbound.ai/api/v1/capabilities

Response Format

All responses use a consistent JSON envelope with a data key for successful requests and an error key for failures. Successful responses include a meta object with a unique request ID.

Response fields

FieldTypeDescription
dataobjectResponse payload (success only)
errorobjectError details with code and message (error only)
metaobjectRequest metadata (requestId, credits)

Success — 200

{
 "data": {
 "contacts": [ ... ]
 },
 "meta": {
 "requestId": "req_abc123def456",
 "credits": { "used": 1 }
 }
}

Error — 4xx / 5xx

{
 "error": {
 "code": "API_KEY_INVALID",
 "message": "Invalid API key.",
 "requestId": "req_abc123def456"
 }
}

Error Codes

When a request fails, the response includes an error object with a machine-readable code and a human-readable message.

CodeStatusDescription
MISSING_API_KEY401No API key was provided in the request.
API_KEY_INVALID401The API key provided is not valid.
API_KEY_EXPIRED401The API key has expired.
API_KEY_REVOKED401The API key has been revoked.
INSUFFICIENT_SCOPE403The key lacks the required scope for this endpoint.
VALIDATION_ERROR400Request validation failed. Check the details array.
RATE_LIMIT_EXCEEDED429Too many requests. Check the Retry-After header.
NOT_FOUND404The requested resource does not exist.
INTERNAL_ERROR500Unexpected server error. Contact support if persistent.
GET/v1

API root. Returns version information, available endpoints, and authentication details. Does not require authentication.

AuthNone required
ScopeNone required

Response body

FieldTypeDescription
namestringAPI name
versionstringSemantic version
endpointsobjectMap of available endpoints with path, method, scope
authenticationobjectSupported auth methods and key format

Request

curl https://app.owlbound.ai/api/v1

Response

{
 "name": "Owlbound API",
 "version": "1.0.0",
 "endpoints": {
 "contacts.list": {
 "path": "/api/v1/contacts",
 "method": "GET",
 "scope": "contacts:read"
 },
 ...
 },
 "authentication": {
 "methods": [
 "X-API-Key header",
 "Authorization: Bearer <key>"
 ],
 "keyFormat": "gtm_sk_* (secret) or gtm_pk_* (publishable)"
 }
}
GET/v1/health

Health check endpoint. Use this to monitor API availability from your infrastructure. Does not require authentication.

AuthNone required
ScopeNone required

Response body

FieldTypeDescription
statusstring"operational"
timestampstringISO 8601 timestamp
versionstringAPI version

Request

curl https://app.owlbound.ai/api/v1/health

Response

{
 "status": "operational",
 "timestamp": "2025-01-15T10:30:00Z",
 "version": "1.0.0"
}
GET/v1/me

Returns information about the authenticated API key including workspace name, key type, granted scopes, and current rate limits. Useful for verifying key configuration.

AuthRequired
Scopecontacts:read
Credits0

Response body

FieldTypeDescription
workspace.idstringWorkspace ID
workspace.namestringWorkspace name
workspace.planstringCurrent billing plan
workspace.statusstringWorkspace status (e.g. "active")
apiKey.idstringAPI key ID
apiKey.scopesstring[]Granted scopes

Request

curl https://app.owlbound.ai/api/v1/me \
 -H "X-API-Key: gtm_sk_your_key_here"

Response

{
 "data": {
 "workspace": {
 "id": "k97f...",
 "name": "Acme Corp",
 "plan": "pro",
 "status": "active"
 },
 "apiKey": {
 "id": "j57d...",
 "scopes": [
 "intelligence:read",
 "enrichment:read",
 "enrichment:write",
 "signals:read",
 "signals:write",
 "contacts:read",
 "contacts:write"
 ]
 }
 },
 "meta": {
 "requestId": "req_abc123def456",
 "credits": { "used": 0 }
 }
}
GET/v1/contacts

Returns a paginated list of contacts in your workspace. Supports filtering by status, source, and company, with configurable sorting.

AuthRequired
Scopecontacts:read
Credits1

Query parameters

ParamTypeDescription
limitnumberResults per page (max 100, default 50)
cursorstringPagination cursor from previous response
statusstringFilter: new, ready, contacted, replied, converted, lost
sourcestringFilter: csv, linkedin, api, manual, etc.
companystringFilter by company name (partial match)
sort_bystringcreatedAt (default), score, activityScore
sort_directionstringasc or desc (default)
include_archivedbooleanInclude archived contacts (default false)
curl "https://app.owlbound.ai/api/v1/contacts?status=new&limit=10" \
 -H "X-API-Key: gtm_sk_your_key_here"
{
 "data": {
 "contacts": [
 {
 "id": "k97f...",
 "firstName": "Jane",
 "lastName": "Smith",
 "email": "jane@acme.com",
 "company": "Acme Corp",
 "title": "VP Engineering",
 "status": "new",
 "score": 85,
 "createdAt": 1705312200000
 }
 ],
 "hasMore": true,
 "nextCursor": "k97f..."
 },
 "meta": { "requestId": "req_abc123", "credits": { "used": 1 } }
}
POST/v1/contacts

Create a new contact in your workspace. At least one of firstName, lastName, email, or linkedInUrl is required. Duplicate detection runs on email and LinkedIn URL.

Scopecontacts:write
Credits1

Request body

FieldTypeDescription
firstNamestring?First name
lastNamestring?Last name
emailstring?Email address (duplicate check)
phonestring?Phone number
linkedInUrlstring?LinkedIn profile URL (duplicate check)
companystring?Company name
titlestring?Job title
locationstring?City/region
sourcestring?Origin (default: "api")
tagsstring[]?Tags array
notesstring?Free-text notes
curl -X POST https://app.owlbound.ai/api/v1/contacts \
 -H "X-API-Key: gtm_sk_your_key_here" \
 -H "Content-Type: application/json" \
 -d '{
 "firstName": "Jane",
 "lastName": "Smith",
 "email": "jane@acme.com",
 "company": "Acme Corp",
 "title": "VP Engineering"
 }'
{
 "data": {
 "contactId": "k97f..."
 },
 "meta": { "requestId": "req_abc123", "credits": { "used": 1 } }
}
POST/v1/contacts/search

Full-text search across contacts. Searches name, title, company, email, and tags.

Scopecontacts:read
Credits1

Request body

FieldTypeDescription
querystringSearch query (required)
limitnumber?Max results (default 25, max 100)
statusstring?Filter by status
curl -X POST https://app.owlbound.ai/api/v1/contacts/search \
 -H "X-API-Key: gtm_sk_your_key_here" \
 -H "Content-Type: application/json" \
 -d '{ "query": "VP Engineering", "limit": 10 }'
GET/v1/contacts/:id

Get a single contact by ID. Returns detailed contact information including enrichment data, scores, and connection status.

Scopecontacts:read
Credits1
curl https://app.owlbound.ai/api/v1/contacts/k97f... \
 -H "X-API-Key: gtm_sk_your_key_here"
PATCH/v1/contacts/:id

Update one or more fields on an existing contact. Only include fields you want to change.

Scopecontacts:write
Credits1
curl -X PATCH https://app.owlbound.ai/api/v1/contacts/k97f... \
 -H "X-API-Key: gtm_sk_your_key_here" \
 -H "Content-Type: application/json" \
 -d '{ "status": "contacted", "tags": ["priority", "enterprise"] }'
DELETE/v1/contacts/:id

Archive (soft-delete) a contact. The contact can be restored later from the dashboard. Optionally include a reason.

Scopecontacts:write
Credits1
curl -X DELETE https://app.owlbound.ai/api/v1/contacts/k97f... \
 -H "X-API-Key: gtm_sk_your_key_here"
POST/v1/contacts/:id/enrich

Queue a contact for data enrichment. The system will scrape LinkedIn profile data, find email/phone, analyze activity, check connection status, and score against ICP profiles. This is an asynchronous operation — poll GET /v1/enrichment/:contactId to check progress.

Powered by
ApolloApollo
FullEnrichFullEnrich
ZoomInfoZoomInfo
Scopeenrichment:write
Credits5

Request body (optional)

FieldTypeDescription
prioritystring?critical, high (default), medium, low
forceRefreshboolean?Re-enrich even if data exists
curl -X POST https://app.owlbound.ai/api/v1/contacts/k97f.../enrich \
 -H "X-API-Key: gtm_sk_your_key_here" \
 -H "Content-Type: application/json" \
 -d '{ "priority": "high" }'
GET/v1/enrichment/:contactId

Check enrichment status for a contact. Returns current phase, completed phases, and any errors. Use this to poll for enrichment completion after calling POST /v1/contacts/:id/enrich.

Scopeenrichment:read
Credits0 (free)
curl https://app.owlbound.ai/api/v1/enrichment/k97f... \
 -H "X-API-Key: gtm_sk_your_key_here"
POST/v1/contacts/:id/score

AI-score a contact against a specific ICP (Ideal Customer Profile). Returns a 0-100 score, verdict, breakdown by category, and reasoning. This is a synchronous operation that calls the AI model in real time.

Scopeintelligence:read
Credits3

Request body

FieldTypeDescription
icpProfileIdstringICP Profile ID to score against (required)
curl -X POST https://app.owlbound.ai/api/v1/contacts/k97f.../score \
 -H "X-API-Key: gtm_sk_your_key_here" \
 -H "Content-Type: application/json" \
 -d '{ "icpProfileId": "jd83..." }'
GET/v1/signals

List combined intent and social signals. Returns a unified view of job changes, funding rounds, social posts, and other buying signals.

Scopesignals:read
Credits1

Query parameters

ParamTypeDescription
typestring?Filter by type: job_change, company_growth, funding_round, website_visit, content_download, job_posting, technology_adoption, custom_webhook
prioritystring?high, medium, low
limitnumber?Max results (default 50, max 100)
unactioned_onlyboolean?Only show unactioned signals
curl "https://app.owlbound.ai/api/v1/signals?priority=high&limit=20" \
 -H "X-API-Key: gtm_sk_your_key_here"
POST/v1/signals

Ingest an external intent signal. Use this to send buying signals from your own systems, webhooks, or third-party tools into the GTM platform. This endpoint works with publishable keys.

Scopesignals:write
Credits1

Request body

FieldTypeDescription
typestringRequired. One of: job_change, company_growth, funding_round, website_visit, content_download, job_posting, technology_adoption, custom_webhook
dataobjectRequired. Signal-specific data (max 10KB)
contactIdstring?Link to existing contact
prioritystring?high, medium (default), low
sourcestring?Source identifier (default: "api")
notesstring?Free-text notes about the signal
curl -X POST https://app.owlbound.ai/api/v1/signals \
 -H "X-API-Key: gtm_pk_your_key_here" \
 -H "Content-Type: application/json" \
 -d '{
 "type": "website_visit",
 "data": {
 "pageUrl": "/pricing",
 "referrer": "https://google.com",
 "company": { "name": "Acme Corp", "domain": "acme.com" }
 },
 "priority": "high",
 "source": "website_tracker"
 }'
GET/v1/signals/stats

Get signal statistics by type and priority for a given time range. Useful for dashboards and reporting.

Scopesignals:read
Credits0 (free)

Query parameters

time_rangestring?day, week (default), month
curl "https://app.owlbound.ai/api/v1/signals/stats?time_range=week" \
 -H "X-API-Key: gtm_sk_your_key_here"
GET/v1/companies

List companies in your workspace with optional industry filter and pagination.

Scopecontacts:read
Credits1

Query parameters

limitnumber?Max results (default 25, max 50)
industrystring?Filter by industry
cursorstring?Pagination cursor
curl "https://app.owlbound.ai/api/v1/companies?industry=SaaS&limit=10" \
 -H "X-API-Key: gtm_sk_your_key_here"
POST/v1/companies

Create or update a company by LinkedIn URL. Existing non-empty fields are preserved so enrichment and CRM data are not overwritten accidentally.

Scopecontacts:write
RequiredlinkedInUrl
curl https://app.owlbound.ai/api/v1/companies \
 -H "X-API-Key: gtm_sk_your_key_here" \
 -H "Content-Type: application/json" \
 -d '{
 "linkedInUrl": "https://www.linkedin.com/company/acme",
 "name": "Acme Corp",
 "domain": "acme.com",
 "industry": "SaaS"
}'
GET/v1/companies/:id

Get a single company by ID with full details and contact count.

Scopecontacts:read
Credits1
curl https://app.owlbound.ai/api/v1/companies/p12f... \
 -H "X-API-Key: gtm_sk_your_key_here"
POST/v1/sequences/:id/enroll

Enroll a contact into an active outreach sequence. The API checks workspace ownership, exclusion rules, archived status, duplicate active enrollments, and sequence steps.

Scopesequences:write
BodycontactId, source?
curl https://app.owlbound.ai/api/v1/sequences/seq123/enroll \
 -H "X-API-Key: gtm_sk_your_key_here" \
 -H "Content-Type: application/json" \
 -d '{ "contactId": "contact123", "source": "api" }'
POST/v1/workflows/:id/trigger

Trigger an active signal workflow for a contact by creating a custom webhook signal and routing it through the signal router.

Scopeworkflows:write
BodycontactId, data?
curl https://app.owlbound.ai/api/v1/workflows/wf123/trigger \
 -H "X-API-Key: gtm_sk_your_key_here" \
 -H "Content-Type: application/json" \
 -d '{ "contactId": "contact123", "data": { "source": "webhook" } }'
GET/v1/connectors

List connector instances with redacted configuration and computed health. Use it to power connector dashboards, external monitoring, and agent audits.

Scopeconnectors:read
FiltersintegrationSlug?, includeArchived?
curl "https://app.owlbound.ai/api/v1/connectors?integrationSlug=slack" \
 -H "X-API-Key: gtm_sk_your_key_here"
GET/v1/connectors/:id

Get one connector with its redacted setup and latest computed health status.

Scopeconnectors:read
curl https://app.owlbound.ai/api/v1/connectors/conn123 \
 -H "X-API-Key: gtm_sk_your_key_here"

Best Practices

Keep secret keys secure
Never expose secret keys (gtm_sk_) in client-side code, public repositories, or browser devtools. Store them as environment variables or in a secrets manager. Use publishable keys for client-side signal ingestion. If a secret key is compromised, rotate it immediately from the Developer tab.
Rotate keys regularly
Set an expiration when creating keys, or rotate them on a regular schedule (e.g. every 90 days). Key rotation atomically creates a new key and revokes the old one, so there's minimal downtime — just update the key in your application after rotation.
Handle errors and retries
Always check the HTTP status code before parsing the response body. Use the error.code field for programmatic handling and error.message for logging. Implement exponential backoff for transient failures (5xx errors). Never retry 4xx errors without fixing the request.
Respect rate limits
Monitor X-RateLimit-Remaining in response headers. When you receive a 429, wait for the duration in the Retry-After header. Consider caching responses to reduce request volume. If you consistently hit limits, contact us about an Enterprise plan.

Start building on Owlbound

Create an API key and integrate contacts, signals, and AI scoring into your workflow.