keap
# 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": "user@example.com",
"sub": "1",
"id": "4236128",
"keap_id": "user@example.com",
"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": "john@example.com", "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/contacts?filter=email_addresses.email==john@example.com
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:support@maton.ai)
标签
skill
ai