API Integration Handbook
Developer20 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/v1Rate 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.
- Navigate to Settings > API Keys in your dashboard
- Click "Generate New Key"
- Select the appropriate scopes (read, write, admin)
- 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
| Method | Endpoint | Description |
|---|---|---|
| GET | /contracts | List all contracts |
| POST | /contracts | Create a new contract |
| GET | /contracts/:id | Get a specific contract |
| PUT | /contracts/:id | Update a contract |
| DELETE | /contracts/:id | Delete a contract |
| POST | /contracts/:id/send | Send contract for signature |
Templates
List, get, and clone contract templates
| Method | Endpoint | Description |
|---|---|---|
| GET | /templates | List all templates |
| GET | /templates/:id | Get a specific template |
| POST | /templates/:id/clone | Clone a template |
Contacts
Manage signers and contract parties
| Method | Endpoint | Description |
|---|---|---|
| GET | /contacts | List all contacts |
| POST | /contacts | Create a new contact |
| PUT | /contacts/:id | Update a contact |
| DELETE | /contacts/:id | Delete a contact |
Webhooks
Subscribe to contract events
| Method | Endpoint | Description |
|---|---|---|
| GET | /webhooks | List all webhook subscriptions |
| POST | /webhooks | Create a webhook subscription |
| DELETE | /webhooks/:id | Delete 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 titlesigners- At least one signersigners[].email- Signer email
Optional Fields
template_id- Use a templatevariables- Template variablesmetadata- Custom metadataoptions- 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
| Event | Description |
|---|---|
| contract.created | A new contract has been created |
| contract.sent | Contract sent to signers |
| contract.viewed | Contract viewed by a signer |
| contract.signed | Contract signed by a signer |
| contract.completed | All signers have signed |
| contract.declined | Contract declined by a signer |
| contract.expired | Contract 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
CRM Systems
- Salesforce - Opportunity contracts
- HubSpot - Deal workflows
- Pipedrive - Sales automation
Payment Platforms
- Paystack - Payment agreements
- Flutterwave - Merchant contracts
- Stripe - Subscription agreements
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
SDKs & Libraries
Use our official SDKs to integrate Baseflow into your applications with less code.
JavaScript/TypeScript SDK
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);Python SDK
Our Python SDK is currently in development. Sign up for updates to be notified when it launches.
Get notifiedError 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 Status | Error Code | Description |
|---|---|---|
| 400 | validation_error | Invalid request parameters |
| 401 | authentication_error | Invalid or missing API key |
| 403 | permission_denied | Insufficient permissions |
| 404 | not_found | Resource does not exist |
| 409 | conflict | Resource state conflict |
| 429 | rate_limit_exceeded | Too many requests |
| 500 | internal_error | Server 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.