Fees

Create a fee

Use this endpoint to create a fee on a project.

A fee represents a financial charge tied to a project — typically a placement fee earned when a candidate is successfully hired.

Splits are required. Every fee must declare how its revenue is distributed across fee earners via splits, and the shares must total exactly 100%.

Placement side effect: when personId refers to a person who is a candidate on the project and has no placement yet, this call also creates a placement, links the fee to it, and emits a placement webhook. If the candidate already has a placement, the fee is linked to the existing one. If the person is not a candidate on the project, the fee is created without a placement. companyContactId and type are only used when a placement is created by this call; type defaults to permanent.

Currency conversion: when currency differs from your agency currency, defaultAmount is computed automatically using the current exchange rate, and the agency currency is snapshotted onto the fee as defaultCurrency.

Defaults: projectFeeStatus defaults to projected; paid also sets paidAt and invoiced also sets invoicedAt. invoiceAccountCode defaults from your agency settings and is not settable on create.

Not supported: contract fees — creating a fee for a candidate with an existing contract placement returns 422.

What you get back: The created fee in the same shape as the fee detail endpoint, so a follow-up GET returns identical fields.

post/api/v1/fees

Request body

projectIdstring uuid required

Project the fee belongs to

amountstring required

Fee amount as a decimal string — not a JSON number

currency'USD' | 'EUR' | 'JPY' | 'GBP' | 'AUD' | 'CAD' | 'CHF' | 'CNY' | 'HKD' | 'NZD' | 'SEK' | 'NOK' | 'MXN' | 'SGD' | 'RUB' | 'ZAR' | 'TRY' | 'BRL' | 'INR' | 'KRW' | 'DKK' | 'PLN' | 'ILS' | 'HUF' | 'CZK' | 'RON' | 'THB' | 'MYR' | 'IDR' | 'VND' | 'PHP' | 'SAR' | 'AED' | 'QAR' | 'KWD' | 'JOD' | 'CLP' | 'COP' | 'PEN' | 'ARS' | 'UYU' | 'CRC' | 'PKR' | 'BDT' | 'LKR' | 'EGP' | 'NGN' | 'TWD' | 'KES' | 'GHS' | 'UGX' | 'TZS' | 'MAD' | 'BWP' | 'BGN' | 'UAH' | 'KZT' | 'GEL' | 'ISK' | 'BHD' | 'OMR' required

Fee currency (ISO 4217)

feeDatestring required

Effective date of the fee (YYYY-MM-DD)

projectFeeStatus'projected' | 'earned' | 'invoiced' | 'paid'

Fee lifecycle status — defaults to projected. paid also sets paidAt; invoiced also sets invoicedAt

personIdstring uuid

Links the fee to a person. When the person is a candidate on the project without an existing placement, a placement is created and linked to the fee

feeTypeIdstring uuid

Fee type ID

notesstring nullable

Fee notes

companyContactIdstring uuid

Only used when this call creates a placement

type'permanent' | 'placement'

Placement type — only used when this call creates a placement. Defaults to permanent. Legacy placement is accepted and normalised to permanent. Contract fees are not supported by this endpoint

Example request

{
  "projectId": "550e8400-e29b-41d4-a716-446655440000",
  "amount": "15000.00",
  "currency": "GBP",
  "feeDate": "2025-06-15",
  "projectFeeStatus": "projected",
  "type": "permanent",
  "splits": [
    {
      "feeEarnerId": "550e8400-e29b-41d4-a716-446655440000",
      "feeTypeId": "660e8400-e29b-41d4-a716-446655440001",
      "share": "60.00"
    }
  ]
}

Response

Fee created

status'ok' required

Example response

{
  "data": {
    "feeType": {
      "name": "Placement Fee"
    },
    "feeDate": "2025-06-15",
    "amount": "15000.00",
    "defaultAmount": "15000.00",
    "currency": "GBP",
    "defaultCurrency": "GBP",
    "projectFeeStatus": "earned",
    "splits": [
      {
        "feeEarner": {
          "name": "Jane Smith",
          "email": "jane@agency.com"
        },
        "feeType": {
          "name": "Placement Fee"
        },
        "share": "60.00"
      }
    ]
  }
}

Changes

Changed in 1 of the 6 revisions of this API.1