What's new in the Knock2 API (August 2026)
Knock2 API Updates: August 2026
API Updates · August 2026

What's new in the Knock2 API

A wave of new features for teams building on Knock2: per-tenant credit controls, fleet-wide reads and webhooks, full tenant lifecycle management, and a smarter enrichment engine.

Explore the API Docs

Everything that shipped

If you manage customer workspaces ("tenants") under a parent Knock2 account, this release is for you. Here's the quick tour, with details and examples below.

Per-tenant credit limits

Allocate a slice of your credit pool to each tenant, in credits, contacts, or accounts, on the schedule you choose. Entirely via API.

Usage reporting

Real per-tenant usage numbers, plus a fleet-wide view of every tenant's allocations and consumption in one call.

Limit-reached webhooks

Get notified the moment a tenant exhausts its allocation, instead of finding out from a support ticket.

Cross-tenant reads, one key

Query any of your tenants' accounts, contacts, activity, and scores with your parent API key. No more juggling one key per tenant.

Parent-level webhook fan-in

One webhook subscription on your parent account now covers every tenant, including ones you create later.

Tenant lifecycle management

Rename a tenant, change its domain with full identification re-provisioning, deactivate, and reactivate. All via API.

Full-featured provisioning

New tenants come up with the complete platform feature set enabled and identification live before the create call returns.

Upgraded enrichment engine

A unified multi-source waterfall with smarter identity matching and caching. Better fill rates, same flat 1-credit price.

Spin up fully-loaded workspaces in one call

What happens when I call POST /v1/tenants?

More than before, and faster:

  • Identification is provisioned synchronously. IP-to-company and person identification are enabled for the new tenant before the call returns. The tracking script at script_url is live immediately. No polling, no waiting on a background job.
  • The full platform feature set is enabled by default, including Plays, webhooks, and CRM integrations. A freshly provisioned tenant behaves like a fully onboarded workspace from minute one.
  • You get a ready-to-use API key for the tenant in the response. It's returned exactly once in plaintext, so store it immediately.
  • You can set credit limits in the same call, so "create a tenant with a 100-credit allowance" is one request, not two.
// POST /v1/tenants
{
  "name": "Acme Corp",
  "domain": "acme.com",
  "limits": [
    { "type": "credits", "value": 100, "period": "lifetime" }
  ]
}
Can I update a tenant after creating it?

Yes, this is new. PATCH /v1/tenants/{product_slug} accepts:

  • name: a simple display-value change.
  • domain: treated as a full re-provisioning operation, not just a column write. Our identification providers are re-registered against the new domain, so IP-to-company and person matching immediately track the new site instead of silently continuing to resolve against the old one. The new domain is also validated and checked for conflicts before anything is written.

product_slug is never updatable. It's the tenant's permanent identifier.

I deactivated a tenant. Can I bring it back?

Yes: POST /v1/tenants/{product_slug}/activate is the mirror of DELETE /v1/tenants/{product_slug}. It reactivates the workspace and restores identification service. Reactivation is the supported path for a returning domain, since re-creating the same domain from scratch will return a 409.

Per-tenant credit limits

What problem does this solve?

You can now allocate a slice of your own credit pool to each tenant, programmatically, in natural units, on a window you choose. No more single undifferentiated pool where one noisy tenant can eat your entire plan. This is the feature that makes reseller and white-label economics safe to build on: give every customer a free taste, meter your paid tiers, and never wake up to a drained pool.

How do limits work?

Each tenant can carry up to three limit types simultaneously. All are enforced, and the most restrictive wins:

TypeWhat it capsBlocks
creditsTotal credit spendEverything (identification, enrichment, prospecting)
contactsUnique contacts identifiedThe contact pipeline only
accountsUnique accounts identifiedThe account pipeline only

Each limit runs on a period: billing_period (your plan's cycle), month, week, day, or lifetime.

// PUT /v1/tenants/{product_slug}/limits
{
  "limits": [
    { "type": "credits",  "value": 100, "period": "lifetime" },
    { "type": "contacts", "value": 10,  "period": "week" }
  ]
}

PUT replaces the entire set, so it's idempotent and there's never partial-state ambiguity. DELETE /v1/tenants/{slug}/limits removes all limits, making the tenant unlimited within your pool. And GET /v1/tenants/{slug}/limits shows each limit with live used and remaining values for the current window.

What are "natural units"?

Limit values are always denominated in the thing they cap: 10 contacts means 10 contacts, not 10 credits' worth of contacts. Every response also echoes equivalent_credits so you can reason about cost:

{ "type": "contacts", "value": 10, "period": "week",
  "equivalent_credits": 60, "used": 4, "remaining": 6 }
Can I allocate more than my plan?

Yes, deliberately. Most tenants never use their full slice, so overbooking is normal. Allocate 10 × 500 credits against a 1,500-credit plan if that fits your business. GET /v1/tenants returns allocated_total_credits alongside your plan_credits so you can watch the overbooking ratio. Your own plan-level cap still protects you regardless: it hard-stops the whole account if reached.

What happens when a tenant hits its limit?

Identification for that tenant stops cleanly. It's a hard stop, scoped to whichever pipeline the exhausted limit covers. Your other tenants and your own workspace are unaffected. The window then resets on schedule (a week limit resets Monday 00:00 UTC, and so on), or you can raise the limit at any time.

How fast do limit changes take effect?

Within about 3 minutes. Enforcement status is cached briefly for performance, so treat limit changes as near-real-time rather than instantaneous. Note this cuts both ways: lowering a limit below a tenant's current usage blocks them on the next check.

Can a tenant raise its own limit?

No. The API key provisioned for each tenant carries tenants:read, so a tenant can check its own remaining balance (useful if you surface it in your product), but only a key belonging to the parent account can write limits. Limits are your lever, always.

How do I find out a tenant ran dry, before they email me?

Subscribe to the new tenant.limit_reached webhook event. It fires to your parent-level webhook subscriptions the moment an allocation is exhausted, with the tenant's slug, which limit tripped, and the window:

{
  "product_slug": "acme_com_yourco_com",
  "limit_type": "credits",
  "limit_value": 100.0,
  "period": "lifetime",
  "window_start": "2026-08-01 00:00:00"
}
It's deduplicated (one notification per tenant, per limit, per window), so you can wire it straight into an auto-top-up flow, an upsell email, or a notification to your own customer without debouncing on your side. An exhausted allocation stops being a support ticket and becomes a monetization loop.

Read any tenant's data with one key

Do I still need one API key per tenant to read data?

No. This is one of the biggest quality-of-life changes. Your parent API key can now read any direct child tenant's data on all the read endpoints:

  • GET /v1/accounts and GET /v1/accounts/{id}
  • GET /v1/contacts and GET /v1/contacts/{id}
  • GET /v1/activity
  • GET /v1/scores and GET /v1/scores/recent

Pass the target tenant either way:

GET /v1/contacts
X-Knock-Tenant: acme_com_yourco_com

or GET /v1/contacts?product_slug=... (the header wins if both are present). Omit both and the endpoint reads your own workspace's data, exactly as before. Fully backward compatible.

A few properties worth knowing:

  • Authorization is strict: only direct children of your account resolve. Anything else returns a 404. The API never confirms whether a slug you don't own exists.
  • Rate limiting and request accounting stay attributed to your key, regardless of which tenant you're reading. One key, one predictable rate budget.
  • If you manage 200 tenants, you now hold one secret for your entire read path instead of 200.

One subscription, all tenants

Do I have to register a webhook on every tenant I create?

No. A webhook subscription on your parent account automatically receives events from every child tenant, including tenants created after you registered the subscription. There's no per-tenant registration step, and no failure mode of forgetting one and having that customer silently receive nothing.

Every payload identifies its tenant, so routing on your side is one field:

  • Payloads include the originating product_slug.
  • Deliveries are HMAC-SHA256 signed (X-Knock-Signature); retrieve your full signing key any time via GET /v1/webhooks/{id}/secret.
  • If a tenant also has its own subscription for the same event, both fire. Deliveries carry IDs, so dedupe on the receiving end if you run both.
What events can I subscribe to?
EventWhen it fires
account.identifiedA company was identified from a site visit
contact.identifiedAn individual person was identified on the site
score.changedA lead score was updated for an account or contact
play.triggeredA play (automation) fired for a contact or account
signal.detectedA buyer signal was detected for a watched account or contact
tenant.limit_reachedA child tenant's credit, contact, or account allocation was exhausted
Combined with fan-in, the integration pattern is simple: one subscription, all events, all tenants, route by product_slug.

Know exactly what every tenant consumed

How do I see what a tenant has actually used?

GET /v1/tenants/{product_slug}/usage returns that tenant's own usage (never its parent's or siblings') for any window:

GET /v1/tenants/acme_com_yourco_com/usage?period=week

period accepts billing_period (default), month, week, day, or lifetime. This is the same number the limit system enforces against, so what you see is exactly what's counted.

For the fleet view, GET /v1/tenants lists every tenant with its full allocation set and per-limit used/remaining, plus the account-level allocated_total_credits vs plan_credits. That's a complete billing dashboard for your book of business in one paginated call. Build customer-facing usage meters, internal margin reports, or overage alerts on top of it without any data warehousing.

What scopes do these use?
  • tenants:read (new): list and get tenants, read limits and usage.
  • tenants:write: create, update, deactivate/reactivate tenants, and write limits.

Per-tenant keys are provisioned with tenants:read (self only) plus read/write on their own data. They never receive tenants:write.

A smarter engine behind POST /v1/enrich

What changed?

The endpoint's contract is the same: send an email (optionally a LinkedIn URL), get back a merged enriched profile. But the engine behind it was rebuilt:

  • One unified waterfall across multiple premium data sources, tried in sequence until the profile is filled. You get the union of what the sources know, not one vendor's best guess.
  • Smarter identity matching. The waterfall now keys on the person's identity, not just the literal email string. A personal email no longer blocks a work-email lookup, and identity can be recovered by name plus company when direct keys fail.
  • Intelligent caching. We stop re-asking sources questions we've recently asked, and cached data follows a newest-wins policy bounded by enrichment timestamps. Fresh data, without paying latency for redundant lookups.
  • Non-destructive merging. Enrichment only fills genuinely empty fields on the contact. It never overwrites data you already have.
Pricing is unchanged and simple: flat 1 credit per successful enrichment, regardless of how many sources responded. A miss costs nothing.

The response's contact_id plugs straight into GET /v1/contacts/{id}, and inline lead scoring runs automatically on enriched contacts, so a score is available right away.

Behavior notes

  • Deactivation is a true master switch. A deactivated tenant's API access, identification, and script all stop together. No half-alive states. Reactivation restores all of it together too.
  • 404, not 403. Anywhere you reference a tenant you don't own, the API returns 404. It never confirms the existence of slugs outside your account.
  • Webhook URLs must be HTTPS. Enforced at registration.
  • Limit changes propagate within ~3 minutes (enforcement caching). Design flows accordingly.
  • Store per-tenant API keys at creation time. They're returned in plaintext exactly once.

Ready to build?

The full API reference, with every endpoint, schema, and example in this post, lives in our interactive docs.

View the API Reference
What's new in the Knock2 API (August 2026)

John DiLoreto is the founder & CEO of Knock2

Latest articles

Browse all