Custom Integrations
API usage, webhook setup, building custom connectors
Custom Integrations
Build custom integrations to connect Verk with proprietary tools, automate unique workflows, and extend platform capabilities beyond built-in integrations.
Overview
Custom integrations use Verk's REST API and webhook system to:
- Connect internal company tools to Verk
- Automate workflows specific to your business
- Build custom reporting and analytics
- Create specialized mobile or desktop apps
- Integrate with niche industry tools
Custom integrations require a Pro or Enterprise plan. Free plans have limited API access for personal use only.
API Authentication
All API requests require authentication using API keys.
Create an API Key
- Navigate to API Settings
- Go to Settings → API Keys
- Click Create New Key
- Configure Key
- Name: Descriptive name (e.g., "Mobile App", "CI/CD Pipeline")
- Scope: Choose permissions:
- Read-only (view tasks, projects, users)
- Read-write (create, update, delete)
- Admin (full access including settings)
- Expiration: Set expiration date (optional, recommended)
- Click Generate Key
- Copy and Store
- Copy the key immediately - it won't be shown again
- Store securely (password manager, secrets vault)
- Never commit keys to version control
- Use in Requests
curl -X GET "https://api.verk.com/v1/tasks" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json"
Treat API keys like passwords. Never expose them in client-side code, public repositories, or unsecured storage.
Key Management
Rotate Keys Regularly:
- Set expiration dates on creation
- Rotate every 90 days for security
- Create new key before deleting old
- Update all integrations with new key
Monitor Usage:
- Review API key activity logs
- Check for unusual patterns
- Identify unused keys for deletion
- Track rate limit consumption
Revoke Compromised Keys:
- Go to Settings → API Keys
- Find compromised key
- Click Revoke
- Generate new key
- Update all integrations
REST API
Base URL
https://api.verk.com/v1
All API endpoints use this base URL. Append resource paths:
GET https://api.verk.com/v1/tasks
GET https://api.verk.com/v1/projects
POST https://api.verk.com/v1/tasks
Common Endpoints
Tasks
# List all tasks
GET /tasks
# Get specific task
GET /tasks/{taskId}
# Create task
POST /tasks
{
"title": "New task",
"description": "Task description",
"projectId": "proj_123",
"assigneeId": "user_456",
"priority": "high",
"dueDate": "2024-12-31T23:59:59Z"
}
# Update task
PATCH /tasks/{taskId}
{
"status": "done",
"priority": "low"
}
# Delete task
DELETE /tasks/{taskId}
Projects
# List all projects
GET /projects
# Get specific project
GET /projects/{projectId}
# Create project
POST /projects
{
"name": "New Project",
"description": "Project description",
"icon": "",
"color": "#3b82f6"
}
# Update project
PATCH /projects/{projectId}
{
"name": "Updated Name",
"archived": false
}
# Delete project
DELETE /projects/{projectId}
Users
# List organization members
GET /users
# Get current user
GET /users/me
# Get specific user
GET /users/{userId}
Comments
# Get task comments
GET /tasks/{taskId}/comments
# Create comment
POST /tasks/{taskId}/comments
{
"content": "This is a comment",
"mentions": ["user_123", "user_456"]
}
# Update comment
PATCH /comments/{commentId}
{
"content": "Updated comment"
}
# Delete comment
DELETE /comments/{commentId}
Filtering and Pagination
Query Parameters:
# Filter tasks by project
GET /tasks?projectId=proj_123
# Filter by status
GET /tasks?status=in_progress
# Filter by assignee
GET /tasks?assigneeId=user_456
# Multiple filters
GET /tasks?projectId=proj_123&status=done&priority=high
# Pagination
GET /tasks?page=1&limit=50
# Sorting
GET /tasks?sortBy=dueDate&order=asc
# Date filters
GET /tasks?dueBefore=2024-12-31&dueAfter=2024-01-01
Response Pagination:
{
"data": [...],
"pagination": {
"total": 250,
"page": 1,
"limit": 50,
"totalPages": 5
}
}
Rate Limits
API Quotas by Plan:
| Plan | Requests/Hour | Burst Limit |
|---|---|---|
| Free | 100 | 20/minute |
| Pro | 1,000 | 100/minute |
| Enterprise | 10,000 | 500/minute |
Rate Limit Headers:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 847
X-RateLimit-Reset: 1640995200
Handling Rate Limits:
async function apiRequest(url, options) {
const response = await fetch(url, options)
if (response.status === 429) {
const resetTime = response.headers.get('X-RateLimit-Reset')
const waitTime = resetTime * 1000 - Date.now()
await new Promise(resolve => setTimeout(resolve, waitTime))
return apiRequest(url, options) // Retry
}
return response.json()
}
Implement exponential backoff for retries and cache responses when possible to stay within rate limits.
Error Handling
HTTP Status Codes:
| Code | Meaning | Action |
|---|---|---|
| 200 | Success | Process response |
| 201 | Created | Resource created successfully |
| 400 | Bad Request | Fix request format/data |
| 401 | Unauthorized | Check API key |
| 403 | Forbidden | Check permissions |
| 404 | Not Found | Verify resource ID |
| 429 | Rate Limited | Wait and retry |
| 500 | Server Error | Retry with backoff |
Error Response Format:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Task title is required",
"field": "title"
}
}
Webhooks
Webhooks notify your application of events in real-time.
Create a Webhook
- Navigate to Webhooks
- Go to Settings → Webhooks
- Click Create Webhook
- Configure Webhook
- URL: Your endpoint (must be HTTPS)
- Events: Select events to receive:
task.createdtask.updatedtask.deletedtask.completedcomment.createdproject.createdproject.updated- Secret: Auto-generated for signature verification
- Filters: Optional event filters (project, assignee, etc.)
- Click Create
- Test Webhook
- Click Send Test Event
- Verify your endpoint receives payload
- Check signature verification
- Review logs for any errors
Webhook endpoints must respond within 5 seconds with status 200-299. Timeouts or errors trigger retries with exponential backoff.
Webhook Payload
Request Headers:
Content-Type: application/json
X-Verk-Event: task.created
X-Verk-Signature: sha256=hash_value
X-Verk-Delivery: uuid-delivery-id
Payload Structure:
{
"event": "task.created",
"timestamp": "2024-01-15T14:30:00Z",
"data": {
"taskId": "task_789",
"title": "New task",
"description": "Task description",
"status": "todo",
"projectId": "proj_123",
"assigneeId": "user_456",
"createdBy": "user_789",
"createdAt": "2024-01-15T14:30:00Z"
}
}
Signature Verification
Verify webhook authenticity:
Node.js Example:
const crypto = require('crypto')
function verifyWebhook(payload, signature, secret) {
const hash = crypto
.createHmac('sha256', secret)
.update(JSON.stringify(payload))
.digest('hex')
const expected = `sha256=${hash}`
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature))
}
// Express.js route
app.post('/webhooks/verk', (req, res) => {
const signature = req.headers['x-verk-signature']
const secret = process.env.VERK_WEBHOOK_SECRET
if (!verifyWebhook(req.body, signature, secret)) {
return res.status(401).send('Invalid signature')
}
// Process webhook
const { event, data } = req.body
console.log(`Received ${event}:`, data)
res.status(200).send('OK')
})
Python Example:
import hmac
import hashlib
def verify_webhook(payload, signature, secret):
hash_obj = hmac.new(
secret.encode('utf-8'),
payload.encode('utf-8'),
hashlib.sha256
)
expected = f"sha256={hash_obj.hexdigest()}"
return hmac.compare_digest(expected, signature)
# Flask route
@app.route('/webhooks/verk', methods=['POST'])
def webhook():
signature = request.headers.get('X-Verk-Signature')
secret = os.environ['VERK_WEBHOOK_SECRET']
payload = request.get_data(as_text=True)
if not verify_webhook(payload, signature, secret):
return 'Invalid signature', 401
data = request.json
print(f"Received {data['event']}: {data['data']}")
return 'OK', 200
Webhook Retry Logic
Failed Delivery Handling:
- Immediate Retry: If endpoint returns 5xx or times out
- Exponential Backoff: Retries at 1min, 5min, 15min, 30min, 1hr
- Max Retries: Up to 5 attempts
- Disable After Failures: Webhook disabled after 100 consecutive failures
Monitor Webhook Health:
- Check delivery success rate in webhook settings
- Review failed delivery logs
- Set up alerts for repeated failures
- Update endpoint URL if needed
SDK Libraries
Official SDKs
JavaScript/TypeScript:
npm install @verk/sdk
import { VerkClient } from '@verk/sdk'
const client = new VerkClient({
apiKey: process.env.VERK_API_KEY,
})
// Create a task
const task = await client.tasks.create({
title: 'New task',
projectId: 'proj_123',
assigneeId: 'user_456',
})
// List tasks
const tasks = await client.tasks.list({
projectId: 'proj_123',
status: 'in_progress',
})
// Update task
await client.tasks.update('task_789', {
status: 'done',
})
Python:
pip install verk-sdk
from verk import VerkClient
client = VerkClient(api_key=os.environ['VERK_API_KEY'])
# Create a task
task = client.tasks.create(
title='New task',
project_id='proj_123',
assignee_id='user_456'
)
# List tasks
tasks = client.tasks.list(
project_id='proj_123',
status='in_progress'
)
# Update task
client.tasks.update('task_789', status='done')
Go:
go get github.com/verk/verk-go
import "github.com/verk/verk-go"
client := verk.NewClient(os.Getenv("VERK_API_KEY"))
// Create task
task, err := client.Tasks.Create(&verk.TaskCreate{
Title: "New task",
ProjectID: "proj_123",
AssigneeID: "user_456",
})
// List tasks
tasks, err := client.Tasks.List(&verk.TaskListOptions{
ProjectID: "proj_123",
Status: "in_progress",
})
// Update task
err = client.Tasks.Update("task_789", &verk.TaskUpdate{
Status: "done",
})
Building Custom Connectors
Integration Architecture
Recommended Pattern:
Your App → Verk API
↓
Webhook ← Verk
↓
Your App processes event
↓
Your App → External Service
Example: CRM Integration:
// Sync new Verk tasks to CRM
app.post('/webhooks/verk', async (req, res) => {
const { event, data } = req.body
if (event === 'task.created') {
// Create corresponding CRM record
await crmClient.createLead({
name: data.title,
description: data.description,
assignedTo: data.assigneeId,
})
}
res.status(200).send('OK')
})
// Sync CRM updates back to Verk
crmClient.on('lead.updated', async lead => {
await verkClient.tasks.update(lead.verkTaskId, {
status: mapCRMStatusToVerk(lead.status),
})
})
Best Practices
Error Handling:
- Implement retries with exponential backoff
- Log all errors for debugging
- Handle partial failures gracefully
- Provide user feedback on errors
Data Synchronization:
- Store mapping between systems (Verk ID ↔ External ID)
- Handle conflicts (last-write-wins or manual resolution)
- Implement idempotency for duplicate webhooks
- Queue operations to avoid race conditions
Security:
- Always verify webhook signatures
- Use HTTPS for all webhook endpoints
- Rotate API keys regularly
- Encrypt stored credentials
- Implement request signing
Performance:
- Cache API responses when possible
- Batch API requests to reduce calls
- Use webhooks instead of polling
- Implement request queuing for high volume
- Monitor and optimize rate limit usage
Example Integrations
CI/CD Pipeline Integration
Goal: Create tasks for failed builds
// GitHub Actions workflow
name: Create Verk Task on Build Failure
on:
workflow_run:
workflows: ["Build"]
types: [completed]
jobs:
create-task:
if: $`{{ github.event.workflow_run.conclusion == 'failure' }}`
runs-on: ubuntu-latest
steps:
- name: Create Verk Task
run: |
curl -X POST https://api.verk.com/v1/tasks \
-H "Authorization: Bearer $`{{ secrets.VERK_API_KEY }}`" \
-H "Content-Type: application/json" \
-d '{
"title": "Build Failed: $`{{ github.repository }}`",
"description": "Build failed on $`{{ github.ref }}`",
"projectId": "proj_123",
"priority": "high",
"tags": ["build-failure", "ci-cd"]
}'
Customer Support Integration
Goal: Create tasks from support tickets
# Zendesk webhook handler
@app.route('/webhooks/zendesk', methods=['POST'])
def zendesk_webhook():
ticket = request.json
# Create Verk task for new ticket
verk_client.tasks.create(
title=f"Support: {ticket['subject']}",
description=f"Customer: {ticket['requester']['name']}\n\n{ticket['description']}",
project_id='proj_support',
priority='high' if ticket['priority'] == 'urgent' else 'medium',
tags=['support', f"ticket-{ticket['id']}"]
)
return 'OK', 200
Analytics Dashboard
Goal: Pull Verk data into BI tool
import pandas as pd
from verk import VerkClient
client = VerkClient(api_key=os.environ['VERK_API_KEY'])
# Fetch all completed tasks from last month
tasks = client.tasks.list(
status='done',
completed_after='2024-01-01',
completed_before='2024-01-31'
)
# Convert to DataFrame
df = pd.DataFrame(tasks)
# Calculate metrics
completion_rate = len(df) / total_tasks
avg_completion_time = (df['completed_at'] - df['created_at']).mean()
# Export to BI tool
df.to_csv('monthly_tasks.csv')
Related Documentation
- API Reference - Complete API documentation
- Webhooks - Detailed webhook guide
- SDK Documentation - Official SDK references
- Integration Overview - Built-in integrations
- Security - Security best practices
Custom integrations unlock unlimited possibilities for connecting Verk to your unique tools and workflows.