Skip to content

Payment Terms

MC0RE edited this page Aug 18, 2026 · 3 revisions

Payment Terms

Read payment term definitions in Teamleader Focus.

Overview

Payment terms define when invoices are due. They are used when creating invoices and subscriptions. The response includes a meta.default key identifying the account's default term.

Access via Teamleader::payment_terms().

SDK key uses underscores: payment_terms β€” not camelCase.

paymentTerms.list takes no request body. The specification declares no filter, page or sort parameter. Passing arguments throws since v2.2.0; before that they were silently discarded. All helper methods are client-side β€” they call list() then filter in PHP.

Payment terms are written by shape, not by id. When creating an invoice or subscription you pass ['type' => ..., 'days' => ...], not a term UUID. The ids in this resource are for lookup and display, not for writing. See Using a payment term.

Endpoint

paymentTerms

Capabilities

Capability Supported
Pagination ❌ Not supported
Filtering ❌ Not supported
Sorting ❌ Not supported
Sideloading ❌ Not supported
Creation ❌ Not supported
Update ❌ Not supported
Deletion ❌ Not supported

Methods

list()

Returns all payment terms in a single response. Takes no arguments.

use McoreServices\TeamleaderSDK\Facades\Teamleader;

$terms = Teamleader::payment_terms()->list();

// Access the default term UUID
$defaultId = $terms['meta']['default'];

Any argument throws before the request is sent:

Teamleader::payment_terms()->list([], ['page_size' => 5]);
// InvalidArgumentException: paymentTerms.list does not support pagination.
// Passed: page_size. The endpoint returns every record in a single response,
// so there are no pages to request.

There is no info() endpoint β€” use find() to resolve a single term from the list.


Helper Methods

All helpers call list() then filter in PHP. Each one costs its own API request.

getDefault()

Returns the default payment term object, or null if none is set.

$default = Teamleader::payment_terms()->getDefault();
// ['id' => 'uuid', 'type' => 'after_invoice_date', 'days' => 30]

getDefaultId()

Returns the UUID of the default payment term, or null.

$defaultId = Teamleader::payment_terms()->getDefaultId();

findByType(string $type)

Returns all terms matching the given type, as an array. Throws InvalidArgumentException for invalid types.

Valid types: cash, end_of_month, after_invoice_date

$cashTerms     = Teamleader::payment_terms()->findByType('cash');
$standardTerms = Teamleader::payment_terms()->findByType('after_invoice_date');

findByDays(int $days, ?string $type = null)

Returns the first term matching the given number of days, optionally narrowed by type. Returns null if not found.

$term30 = Teamleader::payment_terms()->findByDays(30);
$term30 = Teamleader::payment_terms()->findByDays(30, 'after_invoice_date');

Note the asymmetry: findByType() returns an array of every match, findByDays() returns a single term or null.

Type shortcuts

Each returns an array, delegating to findByType().

$cashTerms         = Teamleader::payment_terms()->cash();
$endOfMonthTerms   = Teamleader::payment_terms()->endOfMonth();
$afterInvoiceTerms = Teamleader::payment_terms()->afterInvoiceDate();

asOptions()

Returns flat [id => formatted_description] map. Uses formatPaymentTermDescription() internally, because the API returns no description field β€” the human-readable label is built by the SDK from type and days.

$options = Teamleader::payment_terms()->asOptions();
// ['uuid-1' => 'Cash (immediate payment)',
//  'uuid-2' => '30 days after invoice date',
//  'uuid-3' => 'End of month + 15 days']

formatPaymentTermDescription(array $term)

Turns a term object into a readable string. Public, so you can use it on a term you already have without a second lookup.

$label = Teamleader::payment_terms()->formatPaymentTermDescription([
    'type' => 'after_invoice_date',
    'days' => 30,
]);
// '30 days after invoice date'

exists(string $id) / find(string $id) / isValidType(string $type)

$exists = Teamleader::payment_terms()->exists('term-uuid');
$term   = Teamleader::payment_terms()->find('term-uuid'); // array or null
$valid  = Teamleader::payment_terms()->isValidType('cash');

Response Structure

[
    'data' => [
        ['id' => 'uuid-1', 'type' => 'cash'],
        ['id' => 'uuid-2', 'type' => 'after_invoice_date', 'days' => 30],
        ['id' => 'uuid-3', 'type' => 'end_of_month',       'days' => 15],
    ],
    'meta'    => ['default' => 'uuid-2'],
    'headers' => ['X-RateLimit-Remaining' => ['199'], /* ... */],
]

There is no description field. Earlier versions of this page showed one; the API returns only id, type and days. Use asOptions() or formatPaymentTermDescription() to build a label.

days is absent on cash terms β€” the modifier only applies to end_of_month and after_invoice_date.

meta.default is always present on this endpoint. It is unrelated to the includes=pagination metadata other resources return, and needs no request parameter.


Using a payment term

Payment terms are not referenced by id when writing. Both invoices.draft and subscriptions.create take a payment_term object of {type, days}:

Teamleader::invoices()->create([
    'department_id' => 'dept-uuid',
    'invoicee'      => ['customer' => ['type' => 'company', 'id' => 'company-uuid']],
    'payment_term'  => ['type' => 'after_invoice_date', 'days' => 30],
    'grouped_lines' => [/* ... */],
]);

To follow the account's default rather than hard-coding a term, read it and pass its shape through:

$default = Teamleader::payment_terms()->getDefault();

Teamleader::invoices()->create([
    'department_id' => 'dept-uuid',
    'invoicee'      => ['customer' => ['type' => 'company', 'id' => 'company-uuid']],
    'payment_term'  => array_filter([
        'type' => $default['type'],
        'days' => $default['days'] ?? null,
    ], fn ($v) => $v !== null),
    'grouped_lines' => [/* ... */],
]);

days is omitted for cash terms, which is why it is filtered out when absent.


Usage Examples

Build a select list

$options = Cache::remember('tl_payment_terms', 86400, fn () =>
    Teamleader::payment_terms()->asOptions()
);

Terms rarely change, and every helper costs a request β€” worth caching.

Resolve everything in one call

$response = Teamleader::payment_terms()->list();

$terms     = collect($response['data']);
$defaultId = $response['meta']['default'] ?? null;
$default   = $terms->firstWhere('id', $defaultId);
$thirtyDay = $terms->first(fn ($t) => ($t['days'] ?? null) === 30);

Chaining getDefault(), findByDays(30) and cash() instead would be three separate API calls.


Error Handling

use InvalidArgumentException;

// Arguments the endpoint cannot honour
try {
    Teamleader::payment_terms()->list([], ['page_size' => 5]);
} catch (InvalidArgumentException $e) {
    // 'paymentTerms.list does not support pagination. ...'
}

// Invalid type
try {
    Teamleader::payment_terms()->findByType('net_30');
} catch (InvalidArgumentException $e) {
    // "Invalid payment term type 'net_30'. Must be one of: cash,
    //  end_of_month, after_invoice_date"
}

Related Resources

Clone this wiki locally