API Integration Handbook

Developer

20 min read

This comprehensive guide covers everything you need to integrate Baseflow into your applications. From authentication to webhooks, learn how to automate contract workflows programmatically.

API Overview

The Baseflow API is a RESTful API that allows you to programmatically create, manage, and send contracts. All API responses are returned in JSON format.

REST API Introduction

Our API follows REST principles and uses standard HTTP methods. All requests must be made over HTTPS. The API is designed to be predictable and intuitive for developers familiar with modern web APIs.

Base URL

https://api.baseflow.com/v1

Rate Limits

100 requests per minute per API key. Rate limit headers are included in all responses.

Versioning Policy

The API version is included in the URL path. We maintain backward compatibility within major versions and provide 12-month deprecation notices for breaking changes.

Authentication

Baseflow supports multiple authentication methods to suit different integration scenarios. Choose the method that best fits your use case.

API Key Generation

Generate API keys from your Baseflow dashboard under Settings > API Keys. You can create multiple keys with different scopes for various environments.

  1. Navigate to Settings > API Keys in your dashboard
  2. Click "Generate New Key"
  3. Select the appropriate scopes (read, write, admin)
  4. Copy and securely store your key (it won't be shown again)

Bearer Token Authentication

Include your API key as a Bearer token in the Authorization header of all requests.

curl -X GET "https://api.baseflow.com/v1/contracts" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json"

OAuth 2.0 for Partner Integrations

For partner integrations that require access to multiple customer accounts, use OAuth 2.0 with the authorization code flow.

// OAuth 2.0 Authorization URL
https://app.baseflow.com/oauth/authorize?
  client_id=YOUR_CLIENT_ID&
  redirect_uri=YOUR_REDIRECT_URI&
  response_type=code&
  scope=contracts:read contracts:write

Security Best Practices

  • Never expose API keys in client-side code or public repositories
  • Rotate API keys periodically and after any suspected compromise
  • Use environment variables to store API keys in your applications
  • Implement IP allowlisting for production API keys

Core Endpoints

The Baseflow API provides endpoints for managing contracts, templates, contacts, and webhooks. Below is an overview of the main resource endpoints.

Contracts

Create, read, update, delete, and send contracts

MethodEndpointDescription
GET/contractsList all contracts
POST/contractsCreate a new contract
GET/contracts/:idGet a specific contract
PUT/contracts/:idUpdate a contract
DELETE/contracts/:idDelete a contract
POST/contracts/:id/sendSend contract for signature

Templates

List, get, and clone contract templates

MethodEndpointDescription
GET/templatesList all templates
GET/templates/:idGet a specific template
POST/templates/:id/cloneClone a template

Contacts

Manage signers and contract parties

MethodEndpointDescription
GET/contactsList all contacts
POST/contactsCreate a new contact
PUT/contacts/:idUpdate a contact
DELETE/contacts/:idDelete a contact

Webhooks

Subscribe to contract events

MethodEndpointDescription
GET/webhooksList all webhook subscriptions
POST/webhooksCreate a webhook subscription
DELETE/webhooks/:idDelete a webhook subscription

Creating Contracts via API

Learn how to create contracts programmatically with complete request and response examples.

Request Example

POST /v1/contracts
Content-Type: application/json
Authorization: Bearer YOUR_API_KEY

{
  "title": "Service Agreement - Acme Corp",
  "template_id": "tmpl_abc123",
  "variables": {
    "client_name": "Acme Corporation",
    "client_address": "123 Business Ave, Lagos",
    "contract_value": "500,000",
    "start_date": "2026-02-01",
    "end_date": "2027-01-31"
  },
  "signers": [
    {
      "name": "John Doe",
      "email": "[email protected]",
      "role": "Client Representative",
      "order": 1
    },
    {
      "name": "Jane Smith",
      "email": "[email protected]",
      "role": "Account Manager",
      "order": 2
    }
  ],
  "metadata": {
    "deal_id": "deal_xyz789",
    "source": "crm_integration"
  },
  "options": {
    "expiration_days": 30,
    "reminder_frequency": 3,
    "require_all_signers": true
  }
}

Response Example

{
  "id": "con_def456",
  "status": "draft",
  "title": "Service Agreement - Acme Corp",
  "created_at": "2026-02-01T10:30:00Z",
  "updated_at": "2026-02-01T10:30:00Z",
  "expires_at": "2026-03-03T10:30:00Z",
  "signers": [
    {
      "id": "sig_001",
      "name": "John Doe",
      "email": "[email protected]",
      "status": "pending",
      "order": 1
    },
    {
      "id": "sig_002",
      "name": "Jane Smith",
      "email": "[email protected]",
      "status": "pending",
      "order": 2
    }
  ],
  "signing_url": "https://sign.baseflow.com/con_def456",
  "pdf_url": "https://api.baseflow.com/v1/contracts/con_def456/pdf"
}

Required vs Optional Fields

Required Fields

  • title - Contract title
  • signers - At least one signer
  • signers[].email - Signer email

Optional Fields

  • template_id - Use a template
  • variables - Template variables
  • metadata - Custom metadata
  • options - Configuration options

Variable Substitution

Use double curly braces to define variables in your templates. When creating a contract via API, pass the variable values in the variables object.

// Template content
"This agreement is between {{client_name}} and {{company_name}}..."

// API request variables
"variables": {
  "client_name": "Acme Corporation",
  "company_name": "Your Company Ltd"
}

Adding Signers Programmatically

Each signer object supports the following properties:

"signers": [
  {
    "name": "John Doe",           // Display name
    "email": "[email protected]",  // Required: notification email
    "role": "CEO",                // Optional: role/title
    "order": 1,                   // Optional: signing order (1 = first)
    "phone": "+234801234567",     // Optional: for SMS notifications
    "auth_method": "email",       // Optional: email, sms, or id_verification
    "fields": [                   // Optional: pre-fill form fields
      {
        "name": "company",
        "value": "Acme Corp"
      }
    ]
  }
]

Webhooks

Webhooks allow your application to receive real-time notifications when events occur in Baseflow. Configure webhook endpoints to automate your workflows.

Available Events

EventDescription
contract.createdA new contract has been created
contract.sentContract sent to signers
contract.viewedContract viewed by a signer
contract.signedContract signed by a signer
contract.completedAll signers have signed
contract.declinedContract declined by a signer
contract.expiredContract has expired

Setting Up Webhook Endpoints

POST /v1/webhooks
Content-Type: application/json
Authorization: Bearer YOUR_API_KEY

{
  "url": "https://your-app.com/webhooks/baseflow",
  "events": [
    "contract.signed",
    "contract.completed",
    "contract.expired"
  ],
  "secret": "whsec_your_secret_key"
}

Verifying Webhook Signatures (HMAC-SHA256)

All webhook payloads include a signature header for verification. Use HMAC-SHA256 to verify the payload authenticity.

// Node.js example
const crypto = require('crypto');

function verifyWebhookSignature(payload, signature, secret) {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from('sha256=' + expectedSignature)
  );
}

// Express.js webhook handler
app.post('/webhooks/baseflow', (req, res) => {
  const signature = req.headers['x-baseflow-signature'];
  const payload = JSON.stringify(req.body);

  if (!verifyWebhookSignature(payload, signature, WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }

  // Process the webhook
  const event = req.body;
  console.log('Received event:', event.type);

  res.status(200).send('OK');
});

Retry Policy

Baseflow will retry failed webhook deliveries with exponential backoff:

  • Attempt 1: Immediate
  • Attempt 2: After 1 minute
  • Attempt 3: After 5 minutes
  • Attempt 4: After 30 minutes
  • Attempt 5: After 2 hours

Your endpoint must return a 2xx status code within 30 seconds to be considered successful.

Common Integrations

Baseflow integrates seamlessly with popular business tools. Here are guides for the most common integration scenarios.

HR Platforms

  • SeamlessHR - Employee onboarding
  • Workpay - Payroll contracts
  • BambooHR - Offer letters
View HR integrations

CRM Systems

  • Salesforce - Opportunity contracts
  • HubSpot - Deal workflows
  • Pipedrive - Sales automation
View CRM integrations

Payment Platforms

  • Paystack - Payment agreements
  • Flutterwave - Merchant contracts
  • Stripe - Subscription agreements
View payment integrations

Zapier Connection

Connect Baseflow to 5,000+ apps with no code using Zapier.

  • Trigger: Contract signed
  • Trigger: Contract completed
  • Action: Create contract
  • Action: Send for signature
View on Zapier

SDKs & Libraries

Use our official SDKs to integrate Baseflow into your applications with less code.

JavaScript/TypeScript SDK

Available
npm install @baseflow/sdk
import { Baseflow } from '@baseflow/sdk';

const baseflow = new Baseflow({
  apiKey: process.env.BASEFLOW_API_KEY
});

// Create a contract
const contract = await baseflow.contracts.create({
  title: 'Service Agreement',
  signers: [
    { name: 'John Doe', email: '[email protected]' }
  ]
});

// Send for signature
await baseflow.contracts.send(contract.id);
View on GitHub

Python SDK

Coming Soon

Our Python SDK is currently in development. Sign up for updates to be notified when it launches.

Get notified

Community Libraries

Community-maintained libraries for other languages:

Error Handling

Understanding error responses is essential for building robust integrations. All errors follow a consistent format.

Error Response Format

{
  "error": {
    "code": "validation_error",
    "message": "The request body is invalid",
    "details": [
      {
        "field": "signers[0].email",
        "message": "Invalid email format"
      }
    ],
    "request_id": "req_abc123xyz"
  }
}

Common Error Codes

HTTP StatusError CodeDescription
400validation_errorInvalid request parameters
401authentication_errorInvalid or missing API key
403permission_deniedInsufficient permissions
404not_foundResource does not exist
409conflictResource state conflict
429rate_limit_exceededToo many requests
500internal_errorServer error (contact support)

Troubleshooting Guide

401 Authentication Errors

  • - Verify your API key is correct and not expired
  • - Check the Authorization header format: "Bearer YOUR_API_KEY"
  • - Ensure the API key has the required scopes

429 Rate Limit Errors

  • - Implement exponential backoff for retries
  • - Check the Retry-After header for wait time
  • - Consider caching responses to reduce requests

500 Server Errors

  • - Include the request_id when contacting support
  • - Check our status page for ongoing incidents
  • - Retry with exponential backoff (max 3 retries)

Ready to start building?

Get your API key and start integrating Baseflow into your applications.