ClawSkills logoClawSkills

Keap

Keap API integration with managed OAuth. Manage contacts, companies, tags, tasks, orders, opportunities, and campaigns for CRM and marketing automation. Use thi

Introduction

# Keap

Access the Keap API with managed OAuth authentication. Manage contacts, companies, tags, tasks, orders, opportunities, campaigns, and more for CRM and marketing automation.

## Quick Start

```bash # List contacts python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/keap/crm/rest/v2/contacts?page_size=10') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```

## Base URL

``` https://gateway.maton.ai/keap/crm/rest/{api-path} ```

The gateway proxies requests to `api.infusionsoft.com/crm/rest` and automatically injects your OAuth token.

## Authentication

All requests require the Maton API key in the Authorization header:

``` Authorization: Bearer $MATON_API_KEY ```

**Environment Variable:** Set your API key as `MATON_API_KEY`:

```bash export MATON_API_KEY="YOUR_API_KEY" ```

### Getting Your API Key

1. Sign in or create an account at [maton.ai](https://maton.ai) 2. Go to [maton.ai/settings](https://maton.ai/settings) 3. Copy your API key

## Connection Management

Manage your Keap OAuth connections at `https://ctrl.maton.ai`.

### List Connections

```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.maton.ai/connections?app=keap&status=ACTIVE') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```

### Create Connection

```bash python <<'EOF' import urllib.request, os, json data = json.dumps({'app': 'keap'}).encode() req = urllib.request.Request('https://ctrl.maton.ai/connections', data=data, method='POST') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```

### Get Connection

```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```

**Response:** ```json { "connection": { "connection_id": "d5242090-02ae-4195-83e3-8deca823eb9a", "status": "ACTIVE", "creation_time": "2026-02-08T01:34:44.738374Z", "last_updated_time": "2026-02-08T01:35:20.106942Z", "url": "https://connect.maton.ai/?session_token=...", "app": "keap", "metadata": {} } } ```

Open the returned `url` in a browser to complete OAuth authorization.

### Delete Connection

```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}', method='DELETE') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```

### Specifying Connection

If you have multiple Keap connections, specify which one to use with the `Maton-Connection` header:

```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/keap/crm/rest/v2/contacts') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Maton-Connection', 'd5242090-02ae-4195-83e3-8deca823eb9a') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```

If omitted, the gateway uses the default (oldest) active connection.

## API Reference

### User Info

#### Get Current User

```bash GET /keap/crm/rest/v2/oauth/connect/userinfo ```

**Response:** ```json { "email": "[email protected]", "sub": "1", "id": "4236128", "keap_id": "[email protected]", "family_name": "Doe", "given_name": "John", "is_admin": true } ```

### Contact Operations

#### List Contacts

```bash GET /keap/crm/rest/v2/contacts ```

Query parameters: - `page_size` - Number of results per page (default 50, max 1000) - `page_token` - Token for next page - `filter` - Filter expression - `order_by` - Sort order - `fields` - Fields to include in response

**Response:** ```json { "contacts": [ { "id": "9", "family_name": "Park", "given_name": "John" } ], "next_page_token": "" } ```

#### Get Contact

```bash GET /keap/crm/rest/v2/contacts/{contact_id} ```

#### Create Contact

```bash POST /keap/crm/rest/v2/contacts Content-Type: application/json

{ "given_name": "John", "family_name": "Doe", "email_addresses": [ {"email": "[email protected]", "field": "EMAIL1"} ], "phone_numbers": [ {"number": "555-1234", "field": "PHONE1"} ] } ```

**Response:** ```json { "id": "13", "family_name": "Doe", "given_name": "John" } ```

#### Update Contact

```bash PATCH /keap/crm/rest/v2/contacts/{contact_id} Content-Type: application/json

{ "given_name": "Jane" } ```

#### Delete Contact

```bash DELETE /keap/crm/rest/v2/contacts/{contact_id} ```

Returns 204 on success.

#### Get Contact Notes

```bash GET /keap/crm/rest/v2/contacts/{contact_id}/notes ```

#### Create Contact Note

```bash POST /keap/crm/rest/v2/contacts/{contact_id}/notes Content-Type: application/json

{ "body": "Note content here", "title": "Note Title" } ```

### Company Operations

#### List Companies

```bash GET /keap/crm/rest/v2/companies ```

#### Get Company

```bash GET /keap/crm/rest/v2/companies/{company_id} ```

#### Create Company

```bash POST /keap/crm/rest/v2/companies Content-Type: application/json

{ "company_name": "Acme Corp", "phone_number": {"number": "555-1234", "type": "MAIN"}, "website": "https://acme.com" } ```

#### Update Company

```bash PATCH /keap/crm/rest/v2/companies/{company_id} Content-Type: application/json

{ "company_name": "Acme Corporation" } ```

#### Delete Company

```bash DELETE /keap/crm/rest/v2/companies/{company_id} ```

### Tag Operations

#### List Tags

```bash GET /keap/crm/rest/v2/tags ```

**Response:** ```json { "tags": [ { "id": "91", "name": "Nurture Subscriber", "description": "", "category": {"id": "10"}, "create_time": "2017-04-24T17:26:26Z", "update_time": "2017-04-24T17:26:26Z" } ], "next_page_token": "" } ```

#### Get Tag

```bash GET /keap/crm/rest/v2/tags/{tag_id} ```

#### Create Tag

```bash POST /keap/crm/rest/v2/tags Content-Type: application/json

{ "name": "VIP Customer", "description": "High value customers" } ```

#### Update Tag

```bash PATCH /keap/crm/rest/v2/tags/{tag_id} Content-Type: application/json

{ "name": "Premium Customer" } ```

#### Delete Tag

```bash DELETE /keap/crm/rest/v2/tags/{tag_id} ```

#### List Contacts with Tag

```bash GET /keap/crm/rest/v2/tags/{tag_id}/contacts ```

#### Apply Tags to Contacts

```bash POST /keap/crm/rest/v2/tags/{tag_id}/contacts:applyTags Content-Type: application/json

{ "contact_ids": ["1", "2", "3"] } ```

#### Remove Tags from Contacts

```bash POST /keap/crm/rest/v2/tags/{tag_id}/contacts:removeTags Content-Type: application/json

{ "contact_ids": ["1", "2", "3"] } ```

### Tag Category Operations

#### List Tag Categories

```bash GET /keap/crm/rest/v2/tags/categories ```

#### Create Tag Category

```bash POST /keap/crm/rest/v2/tags/categories Content-Type: application/json

{ "name": "Customer Segments" } ```

### Task Operations

#### List Tasks

```bash GET /keap/crm/rest/v2/tasks ```

#### Get Task

```bash GET /keap/crm/rest/v2/tasks/{task_id} ```

#### Create Task

```bash POST /keap/crm/rest/v2/tasks Content-Type: application/json

{ "title": "Follow up call", "description": "Call to discuss proposal", "due_date": "2026-02-15T10:00:00Z", "contact": {"id": "9"} } ```

#### Update Task

```bash PATCH /keap/crm/rest/v2/tasks/{task_id} Content-Type: application/json

{ "completed": true } ```

#### Delete Task

```bash DELETE /keap/crm/rest/v2/tasks/{task_id} ```

### Opportunity Operations

#### List Opportunities

```bash GET /keap/crm/rest/v2/opportunities ```

#### Get Opportunity

```bash GET /keap/crm/rest/v2/opportunities/{opportunity_id} ```

#### Create Opportunity

```bash POST /keap/crm/rest/v2/opportunities Content-Type: application/json

{ "opportunity_title": "New Deal", "contact": {"id": "9"}, "stage": {"id": "1"}, "estimated_close_date": "2026-03-01" } ```

#### Update Opportunity

```bash PATCH /keap/crm/rest/v2/opportunities/{opportunity_id} Content-Type: application/json

{ "stage": {"id": "2"} } ```

#### Delete Opportunity

```bash DELETE /keap/crm/rest/v2/opportunities/{opportunity_id} ```

#### List Opportunity Stages

```bash GET /keap/crm/rest/v2/opportunities/stages ```

### Order Operations

#### List Orders

```bash GET /keap/crm/rest/v2/orders ```

#### Get Order

```bash GET /keap/crm/rest/v2/orders/{order_id} ```

#### Create Order

```bash POST /keap/crm/rest/v2/orders Content-Type: application/json

{ "contact": {"id": "9"}, "order_date": "2026-02-08", "order_title": "Product Order" } ```

#### Add Order Item

```bash POST /keap/crm/rest/v2/orders/{order_id}/items Content-Type: application/json

{ "product": {"id": "1"}, "quantity": 2 } ```

### Product Operations

#### List Products

```bash GET /keap/crm/rest/v2/products ```

#### Get Product

```bash GET /keap/crm/rest/v2/products/{product_id} ```

#### Create Product

```bash POST /keap/crm/rest/v2/products Content-Type: application/json

{ "product_name": "Consulting Package", "product_price": 500.00, "product_short_description": "1 hour consulting" } ```

### Campaign Operations

#### List Campaigns

```bash GET /keap/crm/rest/v2/campaigns ```

#### Get Campaign

```bash GET /keap/crm/rest/v2/campaigns/{campaign_id} ```

#### List Campaign Sequences

```bash GET /keap/crm/rest/v2/campaigns/{campaign_id}/sequences ```

#### Add Contacts to Sequence

```bash POST /keap/crm/rest/v2/campaigns/{campaign_id}/sequences/{sequence_id}:addContacts Content-Type: application/json

{ "contact_ids": ["1", "2"] } ```

#### Remove Contacts from Sequence

```bash POST /keap/crm/rest/v2/campaigns/{campaign_id}/sequences/{sequence_id}:removeContacts Content-Type: application/json

{ "contact_ids": ["1", "2"] } ```

### Email Operations

#### List Emails

```bash GET /keap/crm/rest/v2/emails ```

#### Get Email

```bash GET /keap/crm/rest/v2/emails/{email_id} ```

#### Send Email

```bash POST /keap/crm/rest/v2/emails:send Content-Type: application/json

{ "contacts": [{"id": "9"}], "subject": "Hello", "html_content": "<p>Email body</p>" } ```

### User Operations

#### List Users

```bash GET /keap/crm/rest/v2/users ```

#### Get User

```bash GET /keap/crm/rest/v2/users/{user_id} ```

### Subscription Operations

#### List Subscriptions

```bash GET /keap/crm/rest/v2/subscriptions ```

#### Get Subscription

```bash GET /keap/crm/rest/v2/subscriptions/{subscription_id} ```

### Affiliate Operations

#### List Affiliates

```bash GET /keap/crm/rest/v2/affiliates ```

#### Get Affiliate

```bash GET /keap/crm/rest/v2/affiliates/{affiliate_id} ```

### Automation Operations

#### List Automations

```bash GET /keap/crm/rest/v2/automations ```

#### Get Automation

```bash GET /keap/crm/rest/v2/automations/{automation_id} ```

## Pagination

Keap uses token-based pagination:

```bash GET /keap/crm/rest/v2/contacts?page_size=50 ```

**Response:** ```json { "contacts": [...], "next_page_token": "abc123" } ```

For subsequent pages, use the `page_token` parameter:

```bash GET /keap/crm/rest/v2/contacts?page_size=50&page_token=abc123 ```

When `next_page_token` is empty, there are no more pages.

## Filtering

Use the `filter` parameter for filtering results:

```bash GET /keap/crm/rest/v2/contacts?filter=given_name==John GET /keap/crm/rest/v2/[email protected] GET /keap/crm/rest/v2/tasks?filter=completed==false ```

## Code Examples

### JavaScript

```javascript const response = await fetch( 'https://gateway.maton.ai/keap/crm/rest/v2/contacts?page_size=10', { headers: { 'Authorization': `Bearer ${process.env.MATON_API_KEY}` } } ); const data = await response.json(); ```

### Python

```python import os import requests

response = requests.get( 'https://gateway.maton.ai/keap/crm/rest/v2/contacts', headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'}, params={'page_size': 10} ) data = response.json() ```

## Notes

- All API paths must include `/crm/rest` prefix (e.g., `/keap/crm/rest/v2/contacts`) - Keap uses v2 REST API (previous v1 API is deprecated) - Timestamps are in ISO 8601 format - IDs are returned as strings - Pagination uses `page_size` and `page_token` (not offset-based) - Maximum `page_size` is 1000 - IMPORTANT: When piping curl output to `jq` or other commands, environment variables like `$MATON_API_KEY` may not expand correctly in some shell environments

## Error Handling

| Status | Meaning | |--------|---------| | 400 | Missing Keap connection or invalid request | | 401 | Invalid or missing Maton API key | | 403 | Not authorized (check OAuth scopes) | | 404 | Resource not found | | 429 | Rate limited | | 4xx/5xx | Passthrough error from Keap API |

### Troubleshooting: API Key Issues

1. Check that the `MATON_API_KEY` environment variable is set:

```bash echo $MATON_API_KEY ```

2. Verify the API key is valid by listing connections:

```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.maton.ai/connections') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```

### Troubleshooting: Invalid App Name

1. Ensure your URL path starts with `keap`. For example:

- Correct: `https://gateway.maton.ai/keap/crm/rest/v2/contacts` - Incorrect: `https://gateway.maton.ai/crm/rest/v2/contacts`

## Resources

- [Keap Developer Portal](https://developer.infusionsoft.com/) - [Keap REST API V2 Documentation](https://developer.infusionsoft.com/docs/restv2/) - [Getting Started Guide](https://developer.infusionsoft.com/getting-started/) - [OAuth 2.0 Authentication](https://developer.infusionsoft.com/authentication/) - [Maton Community](https://discord.com/invite/dBfFAcefs2) - [Maton Support](mailto:[email protected])

More Products