Verk

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

  1. Navigate to API Settings
  • Go to SettingsAPI Keys
  • Click Create New Key
  1. 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
  1. 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
  1. 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:

  1. Go to SettingsAPI Keys
  2. Find compromised key
  3. Click Revoke
  4. Generate new key
  5. 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:

PlanRequests/HourBurst Limit
Free10020/minute
Pro1,000100/minute
Enterprise10,000500/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:

CodeMeaningAction
200SuccessProcess response
201CreatedResource created successfully
400Bad RequestFix request format/data
401UnauthorizedCheck API key
403ForbiddenCheck permissions
404Not FoundVerify resource ID
429Rate LimitedWait and retry
500Server ErrorRetry 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

  1. Navigate to Webhooks
  • Go to SettingsWebhooks
  • Click Create Webhook
  1. Configure Webhook
  • URL: Your endpoint (must be HTTPS)
  • Events: Select events to receive:
  • task.created
  • task.updated
  • task.deleted
  • task.completed
  • comment.created
  • project.created
  • project.updated
  • Secret: Auto-generated for signature verification
  • Filters: Optional event filters (project, assignee, etc.)
  • Click Create
  1. 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:

  1. Immediate Retry: If endpoint returns 5xx or times out
  2. Exponential Backoff: Retries at 1min, 5min, 15min, 30min, 1hr
  3. Max Retries: Up to 5 attempts
  4. 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')

Custom integrations unlock unlimited possibilities for connecting Verk to your unique tools and workflows.