AsyncAPI 2.6 description of the Keap (formerly Infusionsoft) REST Hooks webhook surface. Keap REST Hooks are subscriptions that are created and managed via the v1 REST API (`POST /rest/v1/hooks`). Once a subscription is in `Verified` status, Keap delivers events to the `hookUrl` registered by the subscriber via HTTP POST with a JSON body. Verification handshake (Immediate Confirmation): When a subscription is created or re-verified, Keap sends a `POST` to the `hookUrl` carrying a temporary `X-Hook-Secret` header. The subscriber must respond with HTTP 200 and echo back the same `X-Hook-Secret` header and value. A Delayed Confirmation flow is also supported via `POST /rest/v1/hooks/{key}/delayedVerify` where the subscriber sends the `X-Hook-Secret` it received back to Keap as a header. Delivery payload: Each delivery contains one or more changed objects of the same event type, up to a maximum of 1000 objects. The body fields documented by Keap are `event_key`, `object_type`, and `object_keys`, where each `object_keys` entry has an `id`, optional `apiUrl`, and a `timestamp`. Event keys use noun.verb dot-syntax (for example `contact.add`, `contact.edit`, `invoice.delete`). The authoritative list of available event keys is exposed at runtime via `GET /rest/v1/hooks/event_keys` - the channels below cover the commonly used contact, contactGroup, opportunity, invoice, order, and subscription events. Retry policy: Deliveries are attempted up to four times. The first attempt occurs 30-60 seconds after the originating change (5-10 minutes for `contactGroup.applied` and `contactGroup.delete`); subsequent attempts occur 30-60 seconds, 5 minutes, and 30 minutes after each prior failure. A response status `<200` or `>=400` (other than `410`) or no response within 30 seconds counts as a failure. A `410` response marks the subscription `Inactive` immediately. After four failed attempts the subscription is marked `Inactive` and can be re-verified via `POST /rest/v1/hooks/{key}/verify`. Sources: - https://developer.infusionsoft.com/docs/rest/ (REST Hooks tag) - https://crm.infusionsoft.com/app/v3/api-docs/V1 - https://developer.infusionsoft.com/rest-hook-documentation/ Note on `X-Hook-Signature`: An HMAC `X-Hook-Signature` header is declared as an optional message header below to accommodate subscriber integrations that expect one. The Keap v1 REST Hooks documentation does not specify a signing algorithm or shared-secret derivation for event deliveries beyond the verification `X-Hook-Secret`; subscribers should consult their Keap account settings to confirm whether signed deliveries are enabled for their app.
View SpecView on GitHubCRMSalesMarketing AutomationSmall BusinessE-CommerceContactsAsyncAPIWebhooksEvents
Channels
hook.verification
subscribeonHookVerification
Subscription verification request
Verification handshake from Keap to the subscriber. Issued when a subscription is created via `POST /rest/v1/hooks` (Immediate Confirmation) or re-verified via `POST /rest/v1/hooks/{key}/verify`. The subscriber must respond with HTTP 200 and echo the `X-Hook-Secret` header back.
contact.add
subscribeonContactAdd
Contact added
A new contact has been created.
contact.edit
subscribeonContactEdit
Contact edited
An existing contact has been edited.
contact.delete
subscribeonContactDelete
Contact deleted
A contact has been deleted.
contactGroup.applied
subscribeonContactGroupApplied
Contact group applied
A contact group (tag) has been applied to one or more contacts. First-attempt delivery for this event type is batched on a 5-10 minute interval rather than the 30-60 second interval used for most event types.
contactGroup.removed
subscribeonContactGroupRemoved
Contact group removed
A contact group (tag) has been removed from one or more contacts.
opportunity.add
subscribeonOpportunityAdd
Opportunity added
A new opportunity has been created.
opportunity.edit
subscribeonOpportunityEdit
Opportunity edited
An existing opportunity has been edited.
opportunity.delete
subscribeonOpportunityDelete
Opportunity deleted
An opportunity has been deleted.
invoice.add
subscribeonInvoiceAdd
Invoice added
A new invoice has been created.
invoice.edit
subscribeonInvoiceEdit
Invoice edited
An existing invoice has been edited.
order.add
subscribeonOrderAdd
Order added
A new e-commerce order has been created.
subscription.add
subscribeonSubscriptionAdd
Subscription added
A new recurring subscription has been created.
subscription.edit
subscribeonSubscriptionEdit
Subscription edited
An existing recurring subscription has been edited.
subscription.delete
subscribeonSubscriptionDelete
Subscription deleted
A recurring subscription has been deleted.
Messages
✉
HookVerification
Subscription verification request
Empty-body verification `POST` issued by Keap to the subscriber's `hookUrl`. The subscriber must respond with HTTP 200 and echo the `X-Hook-Secret` header value to confirm ownership of the endpoint.
✉
ContactAdd
contact.add
One or more contacts have been created in Keap.
✉
ContactEdit
contact.edit
One or more contacts have been edited.
✉
ContactDelete
contact.delete
One or more contacts have been deleted.
✉
ContactGroupApplied
contactGroup.applied
A contact group (tag) was applied to one or more contacts.
✉
ContactGroupRemoved
contactGroup.removed
A contact group (tag) was removed from one or more contacts.
✉
OpportunityAdd
opportunity.add
One or more opportunities have been created.
✉
OpportunityEdit
opportunity.edit
One or more opportunities have been edited.
✉
OpportunityDelete
opportunity.delete
One or more opportunities have been deleted.
✉
InvoiceAdd
invoice.add
One or more invoices have been created.
✉
InvoiceEdit
invoice.edit
One or more invoices have been edited.
✉
OrderAdd
order.add
One or more orders have been created.
✉
SubscriptionAdd
subscription.add
One or more recurring subscriptions have been created.
✉
SubscriptionEdit
subscription.edit
One or more recurring subscriptions have been edited.
✉
SubscriptionDelete
subscription.delete
One or more recurring subscriptions have been deleted.
Servers
https
subscriber{hookUrl}
The subscriber-controlled HTTPS endpoint registered with Keap as `hookUrl` when creating a REST Hook subscription via `POST /rest/v1/hooks`. Keap sends both the verification `POST` (carrying `X-Hook-Secret`) and all subsequent event deliveries to this URL.
asyncapi: '2.6.0'
info:
title: Keap REST Hooks
version: 'v1'
description: |
AsyncAPI 2.6 description of the Keap (formerly Infusionsoft) REST Hooks
webhook surface. Keap REST Hooks are subscriptions that are created and
managed via the v1 REST API (`POST /rest/v1/hooks`). Once a subscription
is in `Verified` status, Keap delivers events to the `hookUrl` registered
by the subscriber via HTTP POST with a JSON body.
Verification handshake (Immediate Confirmation): When a subscription is
created or re-verified, Keap sends a `POST` to the `hookUrl` carrying a
temporary `X-Hook-Secret` header. The subscriber must respond with HTTP
200 and echo back the same `X-Hook-Secret` header and value. A Delayed
Confirmation flow is also supported via `POST /rest/v1/hooks/{key}/delayedVerify`
where the subscriber sends the `X-Hook-Secret` it received back to Keap
as a header.
Delivery payload: Each delivery contains one or more changed objects of
the same event type, up to a maximum of 1000 objects. The body fields
documented by Keap are `event_key`, `object_type`, and `object_keys`,
where each `object_keys` entry has an `id`, optional `apiUrl`, and a
`timestamp`.
Event keys use noun.verb dot-syntax (for example `contact.add`,
`contact.edit`, `invoice.delete`). The authoritative list of available
event keys is exposed at runtime via `GET /rest/v1/hooks/event_keys` -
the channels below cover the commonly used contact, contactGroup,
opportunity, invoice, order, and subscription events.
Retry policy: Deliveries are attempted up to four times. The first
attempt occurs 30-60 seconds after the originating change (5-10 minutes
for `contactGroup.applied` and `contactGroup.delete`); subsequent
attempts occur 30-60 seconds, 5 minutes, and 30 minutes after each
prior failure. A response status `<200` or `>=400` (other than `410`)
or no response within 30 seconds counts as a failure. A `410` response
marks the subscription `Inactive` immediately. After four failed
attempts the subscription is marked `Inactive` and can be re-verified
via `POST /rest/v1/hooks/{key}/verify`.
Sources:
- https://developer.infusionsoft.com/docs/rest/ (REST Hooks tag)
- https://crm.infusionsoft.com/app/v3/api-docs/V1
- https://developer.infusionsoft.com/rest-hook-documentation/
Note on `X-Hook-Signature`: An HMAC `X-Hook-Signature` header is
declared as an optional message header below to accommodate subscriber
integrations that expect one. The Keap v1 REST Hooks documentation
does not specify a signing algorithm or shared-secret derivation for
event deliveries beyond the verification `X-Hook-Secret`; subscribers
should consult their Keap account settings to confirm whether signed
deliveries are enabled for their app.
contact:
name: Keap
url: https://developer.infusionsoft.com/rest-hook-documentation/
email: [email protected]
license:
name: Apache 2.0
url: https://www.apache.org/licenses/LICENSE-2.0
tags:
- name: Keap
- name: Infusionsoft
- name: REST Hooks
- name: Webhooks
- name: CRM
defaultContentType: application/json
servers:
subscriber:
url: '{hookUrl}'
protocol: https
description: |
The subscriber-controlled HTTPS endpoint registered with Keap as
`hookUrl` when creating a REST Hook subscription via
`POST /rest/v1/hooks`. Keap sends both the verification `POST`
(carrying `X-Hook-Secret`) and all subsequent event deliveries to
this URL.
variables:
hookUrl:
description: Subscriber-controlled URL stored on the Keap REST Hook subscription.
default: https://example.com/webhooks/keap
channels:
hook.verification:
description: |
Verification handshake from Keap to the subscriber. Issued when a
subscription is created via `POST /rest/v1/hooks` (Immediate
Confirmation) or re-verified via `POST /rest/v1/hooks/{key}/verify`.
The subscriber must respond with HTTP 200 and echo the
`X-Hook-Secret` header back.
bindings:
http:
type: request
method: POST
bindingVersion: 0.3.0
subscribe:
summary: Subscription verification request
operationId: onHookVerification
message:
$ref: '#/components/messages/HookVerification'
contact.add:
description: A new contact has been created.
bindings:
http:
type: request
method: POST
bindingVersion: 0.3.0
subscribe:
summary: Contact added
operationId: onContactAdd
message:
$ref: '#/components/messages/ContactAdd'
contact.edit:
description: An existing contact has been edited.
bindings:
http:
type: request
method: POST
bindingVersion: 0.3.0
subscribe:
summary: Contact edited
operationId: onContactEdit
message:
$ref: '#/components/messages/ContactEdit'
contact.delete:
description: A contact has been deleted.
bindings:
http:
type: request
method: POST
bindingVersion: 0.3.0
subscribe:
summary: Contact deleted
operationId: onContactDelete
message:
$ref: '#/components/messages/ContactDelete'
contactGroup.applied:
description: |
A contact group (tag) has been applied to one or more contacts.
First-attempt delivery for this event type is batched on a 5-10
minute interval rather than the 30-60 second interval used for
most event types.
bindings:
http:
type: request
method: POST
bindingVersion: 0.3.0
subscribe:
summary: Contact group applied
operationId: onContactGroupApplied
message:
$ref: '#/components/messages/ContactGroupApplied'
contactGroup.removed:
description: A contact group (tag) has been removed from one or more contacts.
bindings:
http:
type: request
method: POST
bindingVersion: 0.3.0
subscribe:
summary: Contact group removed
operationId: onContactGroupRemoved
message:
$ref: '#/components/messages/ContactGroupRemoved'
opportunity.add:
description: A new opportunity has been created.
bindings:
http:
type: request
method: POST
bindingVersion: 0.3.0
subscribe:
summary: Opportunity added
operationId: onOpportunityAdd
message:
$ref: '#/components/messages/OpportunityAdd'
opportunity.edit:
description: An existing opportunity has been edited.
bindings:
http:
type: request
method: POST
bindingVersion: 0.3.0
subscribe:
summary: Opportunity edited
operationId: onOpportunityEdit
message:
$ref: '#/components/messages/OpportunityEdit'
opportunity.delete:
description: An opportunity has been deleted.
bindings:
http:
type: request
method: POST
bindingVersion: 0.3.0
subscribe:
summary: Opportunity deleted
operationId: onOpportunityDelete
message:
$ref: '#/components/messages/OpportunityDelete'
invoice.add:
description: A new invoice has been created.
bindings:
http:
type: request
method: POST
bindingVersion: 0.3.0
subscribe:
summary: Invoice added
operationId: onInvoiceAdd
message:
$ref: '#/components/messages/InvoiceAdd'
invoice.edit:
description: An existing invoice has been edited.
bindings:
http:
type: request
method: POST
bindingVersion: 0.3.0
subscribe:
summary: Invoice edited
operationId: onInvoiceEdit
message:
$ref: '#/components/messages/InvoiceEdit'
order.add:
description: A new e-commerce order has been created.
bindings:
http:
type: request
method: POST
bindingVersion: 0.3.0
subscribe:
summary: Order added
operationId: onOrderAdd
message:
$ref: '#/components/messages/OrderAdd'
subscription.add:
description: A new recurring subscription has been created.
bindings:
http:
type: request
method: POST
bindingVersion: 0.3.0
subscribe:
summary: Subscription added
operationId: onSubscriptionAdd
message:
$ref: '#/components/messages/SubscriptionAdd'
subscription.edit:
description: An existing recurring subscription has been edited.
bindings:
http:
type: request
method: POST
bindingVersion: 0.3.0
subscribe:
summary: Subscription edited
operationId: onSubscriptionEdit
message:
$ref: '#/components/messages/SubscriptionEdit'
subscription.delete:
description: A recurring subscription has been deleted.
bindings:
http:
type: request
method: POST
bindingVersion: 0.3.0
subscribe:
summary: Subscription deleted
operationId: onSubscriptionDelete
message:
$ref: '#/components/messages/SubscriptionDelete'
components:
messageTraits:
HookDeliveryHeaders:
headers:
type: object
properties:
Content-Type:
type: string
const: application/json
User-Agent:
type: string
description: User-Agent string identifying the Keap REST Hook dispatcher.
X-Hook-Signature:
type: string
description: |
Optional HMAC signature header. The Keap v1 REST Hooks
documentation does not formally specify a delivery-signing
algorithm; this header is declared optional to accommodate
integrations that expect a signed delivery. Implementers
should not assume an algorithm without confirming it with
Keap support or their app configuration.
messages:
HookVerification:
name: HookVerification
title: Subscription verification request
summary: |
Empty-body verification `POST` issued by Keap to the subscriber's
`hookUrl`. The subscriber must respond with HTTP 200 and echo the
`X-Hook-Secret` header value to confirm ownership of the endpoint.
contentType: application/json
headers:
type: object
required:
- X-Hook-Secret
properties:
X-Hook-Secret:
type: string
description: |
Temporary secret generated by Keap. The subscriber must
return this exact value in the `X-Hook-Secret` response
header along with a 200 status code to verify the
subscription.
payload:
type: object
description: |
The verification request has no documented body. Some Keap
dispatchers send an empty body and others send `{}`; subscribers
should treat the body as opaque and rely on the
`X-Hook-Secret` header.
additionalProperties: true
ContactAdd:
name: ContactAdd
title: contact.add
summary: One or more contacts have been created in Keap.
traits:
- $ref: '#/components/messageTraits/HookDeliveryHeaders'
contentType: application/json
payload:
allOf:
- $ref: '#/components/schemas/HookEnvelope'
- type: object
properties:
event_key:
const: contact.add
object_type:
const: contact
ContactEdit:
name: ContactEdit
title: contact.edit
summary: One or more contacts have been edited.
traits:
- $ref: '#/components/messageTraits/HookDeliveryHeaders'
contentType: application/json
payload:
allOf:
- $ref: '#/components/schemas/HookEnvelope'
- type: object
properties:
event_key:
const: contact.edit
object_type:
const: contact
ContactDelete:
name: ContactDelete
title: contact.delete
summary: One or more contacts have been deleted.
traits:
- $ref: '#/components/messageTraits/HookDeliveryHeaders'
contentType: application/json
payload:
allOf:
- $ref: '#/components/schemas/HookEnvelope'
- type: object
properties:
event_key:
const: contact.delete
object_type:
const: contact
ContactGroupApplied:
name: ContactGroupApplied
title: contactGroup.applied
summary: A contact group (tag) was applied to one or more contacts.
traits:
- $ref: '#/components/messageTraits/HookDeliveryHeaders'
contentType: application/json
payload:
allOf:
- $ref: '#/components/schemas/HookEnvelope'
- type: object
properties:
event_key:
const: contactGroup.applied
object_type:
const: contactGroup
ContactGroupRemoved:
name: ContactGroupRemoved
title: contactGroup.removed
summary: A contact group (tag) was removed from one or more contacts.
traits:
- $ref: '#/components/messageTraits/HookDeliveryHeaders'
contentType: application/json
payload:
allOf:
- $ref: '#/components/schemas/HookEnvelope'
- type: object
properties:
event_key:
const: contactGroup.removed
object_type:
const: contactGroup
OpportunityAdd:
name: OpportunityAdd
title: opportunity.add
summary: One or more opportunities have been created.
traits:
- $ref: '#/components/messageTraits/HookDeliveryHeaders'
contentType: application/json
payload:
allOf:
- $ref: '#/components/schemas/HookEnvelope'
- type: object
properties:
event_key:
const: opportunity.add
object_type:
const: opportunity
OpportunityEdit:
name: OpportunityEdit
title: opportunity.edit
summary: One or more opportunities have been edited.
traits:
- $ref: '#/components/messageTraits/HookDeliveryHeaders'
contentType: application/json
payload:
allOf:
- $ref: '#/components/schemas/HookEnvelope'
- type: object
properties:
event_key:
const: opportunity.edit
object_type:
const: opportunity
OpportunityDelete:
name: OpportunityDelete
title: opportunity.delete
summary: One or more opportunities have been deleted.
traits:
- $ref: '#/components/messageTraits/HookDeliveryHeaders'
contentType: application/json
payload:
allOf:
- $ref: '#/components/schemas/HookEnvelope'
- type: object
properties:
event_key:
const: opportunity.delete
object_type:
const: opportunity
InvoiceAdd:
name: InvoiceAdd
title: invoice.add
summary: One or more invoices have been created.
traits:
- $ref: '#/components/messageTraits/HookDeliveryHeaders'
contentType: application/json
payload:
allOf:
- $ref: '#/components/schemas/HookEnvelope'
- type: object
properties:
event_key:
const: invoice.add
object_type:
const: invoice
InvoiceEdit:
name: InvoiceEdit
title: invoice.edit
summary: One or more invoices have been edited.
traits:
- $ref: '#/components/messageTraits/HookDeliveryHeaders'
contentType: application/json
payload:
allOf:
- $ref: '#/components/schemas/HookEnvelope'
- type: object
properties:
event_key:
const: invoice.edit
object_type:
const: invoice
OrderAdd:
name: OrderAdd
title: order.add
summary: One or more orders have been created.
traits:
- $ref: '#/components/messageTraits/HookDeliveryHeaders'
contentType: application/json
payload:
allOf:
- $ref: '#/components/schemas/HookEnvelope'
- type: object
properties:
event_key:
const: order.add
object_type:
const: order
SubscriptionAdd:
name: SubscriptionAdd
title: subscription.add
summary: One or more recurring subscriptions have been created.
traits:
- $ref: '#/components/messageTraits/HookDeliveryHeaders'
contentType: application/json
payload:
allOf:
- $ref: '#/components/schemas/HookEnvelope'
- type: object
properties:
event_key:
const: subscription.add
object_type:
const: subscription
SubscriptionEdit:
name: SubscriptionEdit
title: subscription.edit
summary: One or more recurring subscriptions have been edited.
traits:
- $ref: '#/components/messageTraits/HookDeliveryHeaders'
contentType: application/json
payload:
allOf:
- $ref: '#/components/schemas/HookEnvelope'
- type: object
properties:
event_key:
const: subscription.edit
object_type:
const: subscription
SubscriptionDelete:
name: SubscriptionDelete
title: subscription.delete
summary: One or more recurring subscriptions have been deleted.
traits:
- $ref: '#/components/messageTraits/HookDeliveryHeaders'
contentType: application/json
payload:
allOf:
- $ref: '#/components/schemas/HookEnvelope'
- type: object
properties:
event_key:
const: subscription.delete
object_type:
const: subscription
schemas:
HookEnvelope:
type: object
description: |
The shared envelope for every Keap REST Hook delivery. The body
contains the `event_key`, the `object_type` (resource name), and
an `object_keys` array with one or more changed objects (maximum
1000 per delivery).
required:
- event_key
- object_type
- object_keys
properties:
event_key:
type: string
description: |
Identifier of the event type, in `noun.verb` dot-syntax (for
example `contact.add`). Matches the `eventKey` registered on
the originating REST Hook subscription.
object_type:
type: string
description: Resource name affected by the event (for example `contact`).
object_keys:
type: array
description: |
One or more changed objects of the same `event_key`. A single
delivery contains a maximum of 1000 entries.
minItems: 1
maxItems: 1000
items:
$ref: '#/components/schemas/HookObjectKey'
HookObjectKey:
type: object
required:
- id
- timestamp
properties:
id:
description: Identifier of the changed resource object.
oneOf:
- type: integer
format: int64
- type: string
apiUrl:
type: string
format: uri
description: |
Optional REST API URL where the changed resource can be
retrieved. May be absent depending on the event type.
timestamp:
type: string
format: date-time
description: ISO-8601 timestamp at which the change occurred.