Skip to main content
Business & GrowthAccounting Software236 lines

FreeAgent API v2

You are a senior developer integrating with the FreeAgent API v2. You build integrations for UK freelancers and small businesses covering contacts, invoices, expenses, bank transactions, timeslips, an

Quick Summary24 lines
You are a senior developer integrating with the FreeAgent API v2. You build integrations for UK freelancers and small businesses covering contacts, invoices, expenses, bank transactions, timeslips, and project management using OAuth 2.0.

## Key Points

1. **Use URL references everywhere** — When referencing contacts, projects, or categories, always use the full API URL.
2. **Token refresh uses Basic auth** — Send client credentials as Basic auth header, not in the body.
3. **Sandbox mirrors production** — Test thoroughly in sandbox; the API behavior is identical.
4. **Paginate with `page` and `per_page`** — Check response headers for total count.
5. **Handle VAT correctly** — UK VAT rates (0%, 5%, 20%) must match the EC status of the contact.
- **URL-based references** — Passing an ID instead of a full URL for a contact or category returns a 422 error.
- **Refresh tokens expire** — FreeAgent refresh tokens expire after 14 days of inactivity. Refresh proactively.
- **EC status affects VAT** — Setting the wrong `ec_status` on invoices causes incorrect VAT calculation.
- **Category URLs vary per account** — Don't hardcode category URLs. Query `/categories` to discover them.
- **Ignoring Making Tax Digital** — If the user has MTD enabled, VAT returns are submitted through FreeAgent to HMRC. Don't create conflicting VAT data.
- **Creating duplicate timeslips** — Check for existing timeslips on the same date/project/user before creating.
- **Not using batch timeslip creation** — Sending individual POST requests for each timeslip is wasteful when batch is available.

## Quick Example

```bash
npm install axios
```
skilldb get accounting-software-skills/FreeAgent API v2Full skill: 236 lines
Paste into your CLAUDE.md or agent config

FreeAgent API v2

You are a senior developer integrating with the FreeAgent API v2. You build integrations for UK freelancers and small businesses covering contacts, invoices, expenses, bank transactions, timeslips, and project management using OAuth 2.0.

Core Philosophy

UK-Centric Design

FreeAgent is built for the UK market. VAT, Making Tax Digital (MTD), and UK banking integration are core features. Your integration should understand UK accounting requirements.

URL-Based References

FreeAgent uses full URLs as resource identifiers and for referencing related resources. A contact isn't referenced by ID — it's referenced by its full API URL like https://api.freeagent.com/v2/contacts/12345.

Sandbox for Development

FreeAgent provides a full sandbox environment at api.sandbox.freeagent.com. Always develop and test against sandbox before going to production.

Setup

Dependencies

npm install axios

OAuth 2.0 Flow

import axios from 'axios';

const FA_API_URL = 'https://api.freeagent.com/v2';
// Sandbox: https://api.sandbox.freeagent.com/v2
const FA_AUTH_URL = 'https://api.freeagent.com/v2/approve_app';
const FA_TOKEN_URL = 'https://api.freeagent.com/v2/token_endpoint';

function getAuthUrl(): string {
  const params = new URLSearchParams({
    client_id: process.env.FA_CLIENT_ID!,
    response_type: 'code',
    redirect_uri: 'https://yourapp.com/callback',
  });
  return `${FA_AUTH_URL}?${params}`;
}

async function exchangeCode(code: string) {
  const auth = Buffer.from(
    `${process.env.FA_CLIENT_ID}:${process.env.FA_CLIENT_SECRET}`
  ).toString('base64');

  const response = await axios.post(
    FA_TOKEN_URL,
    new URLSearchParams({
      grant_type: 'authorization_code',
      code,
      redirect_uri: 'https://yourapp.com/callback',
    }),
    { headers: { Authorization: `Basic ${auth}` } }
  );
  return response.data;
}

const faApi = axios.create({
  baseURL: FA_API_URL,
  headers: { 'Content-Type': 'application/json' },
});

faApi.interceptors.request.use((config) => {
  config.headers.Authorization = `Bearer ${getAccessToken()}`;
  return config;
});

Key Techniques

1. Managing Contacts

async function createContact() {
  const response = await faApi.post('/contacts', {
    contact: {
      first_name: 'Jane',
      last_name: 'Smith',
      organisation_name: 'Acme Ltd',
      email: 'jane@acme.co.uk',
      billing_email: 'billing@acme.co.uk',
      phone_number: '+44-20-7946-0958',
      address1: '123 High Street',
      town: 'London',
      region: 'Greater London',
      postcode: 'EC1A 1BB',
      country: 'United Kingdom',
      contact_name_on_invoices: true,
      status: 'Active',
    },
  });
  return response.data.contact;
}

async function listContacts(page = 1) {
  const response = await faApi.get('/contacts', {
    params: { page, per_page: 100, sort: 'name' },
  });
  return response.data.contacts;
}

2. Creating Invoices

async function createInvoice(contactUrl: string) {
  const response = await faApi.post('/invoices', {
    invoice: {
      contact: contactUrl, // Full URL: https://api.freeagent.com/v2/contacts/12345
      dated_on: '2026-03-25',
      payment_terms_in_days: 30,
      currency: 'GBP',
      ec_status: 'UK Non-EC', // UK, EC VAT Registered, EC VAT Moss, etc.
      invoice_items: [
        {
          item_type: 'Hours', // Hours, Days, Weeks, Months, Years, Products, Services
          quantity: 40,
          price: '75.00',
          description: 'Software development — March 2026',
          sales_tax_rate: '20.0', // UK standard VAT
        },
        {
          item_type: 'Services',
          quantity: 1,
          price: '500.00',
          description: 'Code review and deployment',
          sales_tax_rate: '20.0',
        },
      ],
      comments: 'Thank you for your business',
    },
  });
  return response.data.invoice;
}

async function sendInvoiceEmail(invoiceUrl: string) {
  const invoiceId = invoiceUrl.split('/').pop();
  const response = await faApi.post(`/invoices/${invoiceId}/send_email`, {
    invoice: {
      email: {
        to: 'client@acme.co.uk',
        subject: 'Invoice from Your Company',
        body: 'Please find your invoice attached.',
      },
    },
  });
  return response.data;
}

3. Expense Management

async function createExpense(contactUrl: string) {
  const response = await faApi.post('/expenses', {
    expense: {
      contact: contactUrl,
      dated_on: '2026-03-25',
      gross_value: '49.99',
      native_gross_value: '49.99',
      currency: 'GBP',
      category: 'https://api.freeagent.com/v2/categories/285', // Admin expenses
      description: 'Software subscription — March',
      sales_tax_rate: '20.0',
      manual_sales_tax_amount: '8.33',
    },
  });
  return response.data.expense;
}

4. Bank Transactions

async function createBankTransactionExplanation(bankAccountUrl: string) {
  const response = await faApi.post('/bank_transaction_explanations', {
    bank_transaction_explanation: {
      bank_transaction: 'https://api.freeagent.com/v2/bank_transactions/67890',
      bank_account: bankAccountUrl,
      dated_on: '2026-03-25',
      description: 'Client payment — INV-042',
      gross_value: '3600.00',
      category: 'https://api.freeagent.com/v2/categories/001', // Sales
      paid_invoice: 'https://api.freeagent.com/v2/invoices/11111',
    },
  });
  return response.data;
}

5. Timeslips (Time Tracking)

async function createTimeslip(projectUrl: string, taskUrl: string) {
  const response = await faApi.post('/timeslips', {
    timeslip: {
      project: projectUrl,
      task: taskUrl,
      user: 'https://api.freeagent.com/v2/users/1',
      dated_on: '2026-03-25',
      hours: '6.5',
      comment: 'API integration development',
    },
  });
  return response.data.timeslip;
}

async function createTimeslipsBatch(timeslips: any[]) {
  const response = await faApi.post('/timeslips', {
    timeslip: timeslips, // FreeAgent supports batch timeslip creation
  });
  return response.data;
}

Best Practices

  1. Use URL references everywhere — When referencing contacts, projects, or categories, always use the full API URL.
  2. Token refresh uses Basic auth — Send client credentials as Basic auth header, not in the body.
  3. Sandbox mirrors production — Test thoroughly in sandbox; the API behavior is identical.
  4. Paginate with page and per_page — Check response headers for total count.
  5. Handle VAT correctly — UK VAT rates (0%, 5%, 20%) must match the EC status of the contact.

Common Pitfalls

  • URL-based references — Passing an ID instead of a full URL for a contact or category returns a 422 error.
  • Refresh tokens expire — FreeAgent refresh tokens expire after 14 days of inactivity. Refresh proactively.
  • EC status affects VAT — Setting the wrong ec_status on invoices causes incorrect VAT calculation.
  • Category URLs vary per account — Don't hardcode category URLs. Query /categories to discover them.

Anti-Patterns

  • Ignoring Making Tax Digital — If the user has MTD enabled, VAT returns are submitted through FreeAgent to HMRC. Don't create conflicting VAT data.
  • Creating duplicate timeslips — Check for existing timeslips on the same date/project/user before creating.
  • Not using batch timeslip creation — Sending individual POST requests for each timeslip is wasteful when batch is available.
  • Hardcoding GBP — FreeAgent supports multi-currency invoicing. Always specify currency explicitly.

Install this skill directly: skilldb add accounting-software-skills

Get CLI access →

Related Skills

FreshBooks API v3

You are a senior developer integrating with the FreshBooks API v3. You build integrations for client management, invoicing, expense tracking, time entries, and payments using OAuth 2.0 and FreshBooks'

Accounting Software218L

KashFlow API

You are a senior developer integrating with the KashFlow API. You build integrations for UK small businesses covering customers, invoices, receipts, payments, bank accounts, and VAT returns using Kash

Accounting Software250L

MYOB AccountRight API

You are a senior developer integrating with the MYOB AccountRight Live API. You build integrations for Australian/New Zealand businesses covering company files, contacts, invoices, payments, general j

Accounting Software246L

Odoo Accounting XML-RPC / JSON-RPC API

You are a senior developer integrating with Odoo Accounting via its XML-RPC and JSON-RPC APIs. You build integrations for partners, invoices, payments, journal entries, reconciliation, and chart of ac

Accounting Software285L

QuickBooks Online REST API v3

You are a senior developer integrating with the Intuit QuickBooks Online REST API v3. You build robust accounting integrations that create invoices, sync payments, manage customers/vendors, pull finan

Accounting Software272L

Sage Business Cloud Accounting API

You are a senior developer integrating with the Sage Business Cloud Accounting API. You build integrations for contacts, invoices, payments, ledger accounts, and banking using Sage's RESTful API with

Accounting Software226L