Aller au contenu

Invoicing (sales)

This page covers the customer-facing side of the Company API: customers, quotes, customer invoices and credit notes, recurring billing subscriptions, read only commercial documents, invoice templates, and the product catalog used to fill invoice and quote lines.

Customers ($client->customers)

Reads customers regardless of kind (company or individual) and manages their categories and contacts. This resource wires two sub resources, ->companies and ->individuals, which you use to create or update a customer of a specific kind.

Method HTTP Scope Description
list($cursor = null, $limit = null, ...) GET /customers customers:all, customers:readonly List customers, company and individual alike.
get($customerId) GET /customers/{customerId} customers:all, customers:readonly Retrieve a customer by its identifier, company or individual alike.
listCategories($customerId, $cursor = null, $limit = null) GET /customers/{customerId}/categories customers:readonly, customers:all List the categories assigned to a customer.
categorize($customerId, $categories) PUT /customers/{customerId}/categories customers:all Replace the categories assigned to a customer with the given list.
listContacts($customerId, $cursor = null, $limit = null, $sort = null) GET /customers/{customerId}/contacts customers:all, customers:readonly List the contacts of a customer.

CompanyCustomers ($client->customers->companies)

Creates and manages customers that are companies (as opposed to individuals).

Method HTTP Scope Description
create($name, $billingAddress, $vatNumber = null, ...) POST /company_customers customers:all Create a company customer.
get($companyCustomerId) GET /company_customers/{companyCustomerId} customers:all, customers:readonly Retrieve a company customer by its identifier.
update($companyCustomerId, $name = null, ...) PUT /company_customers/{companyCustomerId} customers:all Update a company customer.

IndividualCustomers ($client->customers->individuals)

Creates and manages customers that are individuals (as opposed to companies).

Method HTTP Scope Description
create($firstName, $lastName, $billingAddress, $phone = null, ...) POST /individual_customers customers:all Create an individual customer.
get($individualCustomerId) GET /individual_customers/{individualCustomerId} customers:all, customers:readonly Retrieve an individual customer by its identifier.
update($individualCustomerId, $firstName = null, ...) PUT /individual_customers/{individualCustomerId} customers:all Update an individual customer.

CustomerInvoices ($client->customerInvoices)

Manages customer invoices end to end: draft and finalized invoices, credit notes, e-invoicing imports, categorization, appendices, and reconciliation with bank transactions and payments.

Method HTTP Scope Description
list($cursor = null, $limit = null, ...) GET /customer_invoices customer_invoices:all or customer_invoices:readonly List customer invoices.
create($date, $deadline, $customerId, $invoiceLines, $draft = true, ...) POST /customer_invoices customer_invoices:all Create a customer invoice, as a draft or finalized directly.
get($customerInvoiceId) GET /customer_invoices/{customerInvoiceId} customer_invoices:all or customer_invoices:readonly Retrieve a customer invoice by its identifier.
update($customerInvoiceId, $date = null, ...) PUT /customer_invoices/{customerInvoiceId} customer_invoices:all Update a customer invoice (draft invoices accept more fields than finalized ones).
delete($customerInvoiceId) DELETE /customer_invoices/{customerInvoiceId} customer_invoices:all Delete a draft customer invoice (finalized invoices cannot be deleted).
importFromFile($fileAttachmentId, $date, $deadline, $customerId, $currencyAmountBeforeTax, $currencyAmount, $currencyTax, $invoiceLines, $importAsIncomplete = null, ...) POST /customer_invoices/import customer_invoices:all Import a customer invoice from a file already uploaded through file attachments.
importEInvoice($file, $invoiceOptions = null) POST /customer_invoices/e_invoices/imports customer_invoices:all Import a Factur-X, UBL or CII e-invoice file; the invoice is built asynchronously.
createFromQuote($quoteId, $draft, $externalReference = null, $customerInvoiceTemplateId = null) POST /customer_invoices/create_from_quote customer_invoices:all Create a customer invoice from an existing quote.
sendToPa($customerInvoiceId) POST /customer_invoices/{customerInvoiceId}/send_to_pa customer_invoices:all Send a customer e-invoice to the Partner Agreed (PA) platform.
finalize($customerInvoiceId) PUT /customer_invoices/{customerInvoiceId}/finalize customer_invoices:all Turn a draft invoice into a finalized invoice.
markAsPaid($customerInvoiceId) PUT /customer_invoices/{customerInvoiceId}/mark_as_paid customer_invoices:all Mark a customer invoice as paid.
sendByEmail($customerInvoiceId, $recipients = null) POST /customer_invoices/{customerInvoiceId}/send_by_email customer_invoices:all Send a customer invoice by email.
linkCreditNote($customerInvoiceId, $creditNoteId) POST /customer_invoices/{customerInvoiceId}/link_credit_note customer_invoices:all Link a credit note to a customer invoice.
updateImported($customerInvoiceId, $date = null, ...) PUT /customer_invoices/{customerInvoiceId}/update_imported customer_invoices:all Update an imported customer invoice.
listInvoiceLines($customerInvoiceId, $cursor = null, $limit = null, $sort = null) GET /customer_invoices/{customerInvoiceId}/invoice_lines customer_invoices:all or customer_invoices:readonly List invoice lines for a customer invoice.
listInvoiceLineSections($customerInvoiceId, $cursor = null, $limit = null, $sort = null) GET /customer_invoices/{customerInvoiceId}/invoice_line_sections customer_invoices:all or customer_invoices:readonly List invoice line sections for a customer invoice.
listPayments($customerInvoiceId, $cursor = null, $limit = null, $sort = null) GET /customer_invoices/{customerInvoiceId}/payments customer_invoices:all or customer_invoices:readonly List payments recorded against a customer invoice.
listMatchedTransactions($customerInvoiceId, $cursor = null, $limit = null, $sort = null) GET /customer_invoices/{customerInvoiceId}/matched_transactions customer_invoices:all or customer_invoices:readonly List bank transactions matched to a customer invoice.
matchTransaction($customerInvoiceId, $transactionId) POST /customer_invoices/{customerInvoiceId}/matched_transactions customer_invoices:all Match a bank transaction to a customer invoice.
unmatchTransaction($customerInvoiceId, $transactionId) DELETE /customer_invoices/{customerInvoiceId}/matched_transactions/{transactionId} customer_invoices:all Unmatch a bank transaction from a customer invoice.
listAppendices($customerInvoiceId, $cursor = null, $limit = null) GET /customer_invoices/{customerInvoiceId}/appendices customer_invoices:all or customer_invoices:readonly List appendices attached to a customer invoice.
addAppendix($customerInvoiceId, $file) POST /customer_invoices/{customerInvoiceId}/appendices customer_invoices:all Upload an appendix file (a supporting document) for a customer invoice.
listCategories($customerInvoiceId, $cursor = null, $limit = null) GET /customer_invoices/{customerInvoiceId}/categories customer_invoices:all or customer_invoices:readonly List categories assigned to a customer invoice.
categorize($customerInvoiceId, $categories) PUT /customer_invoices/{customerInvoiceId}/categories customer_invoices:all Replace the categories assigned to a customer invoice.
listCustomHeaderFields($customerInvoiceId, $cursor = null, $limit = null, $sort = null) GET /customer_invoices/{customerInvoiceId}/custom_header_fields customer_invoices:all or customer_invoices:readonly List custom header fields for a customer invoice.

CustomerInvoiceTemplates ($client->customerInvoiceTemplates)

Read only access to the customer invoice templates configured on the company (used to brand and structure generated invoice PDFs).

Method HTTP Scope Description
list($cursor = null, $limit = null, $sort = null) GET /customer_invoice_templates customer_invoice_templates:readonly List customer invoice templates configured on the company.

Quotes ($client->quotes)

Manages quotes sent to customers, including their lines, sections, appendices and status transitions.

Method HTTP Scope Description
list($cursor = null, $limit = null, ...) GET /quotes quotes:all, quotes:readonly List quotes.
create($date, $deadline, $customerId, $invoiceLines, $quoteTemplateId = null, ...) POST /quotes quotes:all Create a quote.
get($quoteId) GET /quotes/{quoteId} quotes:all, quotes:readonly Retrieve a quote by its identifier.
update($quoteId, $date = null, ...) PUT /quotes/{quoteId} quotes:all Update a quote.
listAppendices($quoteId, $cursor = null, $limit = null) GET /quotes/{quoteId}/appendices quotes:all, quotes:readonly List the appendices (attached files) of a quote.
addAppendix($quoteId, $file) POST /quotes/{quoteId}/appendices quotes:all Upload an appendix for a quote.
listInvoiceLines($quoteId, $cursor = null, $limit = null, $sort = null) GET /quotes/{quoteId}/invoice_lines quotes:all, quotes:readonly List the invoice lines of a quote.
listInvoiceLineSections($quoteId, $cursor = null, $limit = null, $sort = null) GET /quotes/{quoteId}/invoice_line_sections quotes:all, quotes:readonly List the invoice line sections of a quote.
sendByEmail($quoteId, $recipients = null) POST /quotes/{quoteId}/send_by_email quotes:all Send a quote by email.
updateStatus($quoteId, $status) PUT /quotes/{quoteId}/update_status quotes:all Update the status of a quote (pending, accepted, denied, invoiced, or expired).

CommercialDocuments ($client->commercialDocuments)

Read only access to commercial documents: proformas, shipping orders and purchasing orders. These are generated from quotes or created directly in the Pennylane app; there is no create, update or delete operation.

Method HTTP Scope Description
list($cursor = null, $limit = null, ...) GET /commercial_documents commercial_documents:all, commercial_documents:readonly List commercial documents.
get($commercialDocumentId) GET /commercial_documents/{commercialDocumentId} commercial_documents:all, commercial_documents:readonly Retrieve a commercial document by its identifier.
listAppendices($commercialDocumentId, $cursor = null, $limit = null) GET /commercial_documents/{commercialDocumentId}/appendices commercial_documents:all, commercial_documents:readonly List the appendices (attached files) of a commercial document.
addAppendix($commercialDocumentId, $file) POST /commercial_documents/{commercialDocumentId}/appendices commercial_documents:all Upload an appendix for a commercial document.
listInvoiceLines($commercialDocumentId, $cursor = null, $limit = null, $sort = null) GET /commercial_documents/{commercialDocumentId}/invoice_lines commercial_documents:all, commercial_documents:readonly List the invoice lines of a commercial document.
listInvoiceLineSections($commercialDocumentId, $cursor = null, $limit = null, $sort = null) GET /commercial_documents/{commercialDocumentId}/invoice_line_sections commercial_documents:all, commercial_documents:readonly List the invoice line sections of a commercial document.

BillingSubscriptions ($client->billingSubscriptions)

Creates and manages recurring billing subscriptions that automatically generate customer invoices on a schedule (yearly, monthly or weekly).

Method HTTP Scope Description
list($cursor = null, $limit = null, ...) GET /billing_subscriptions billing_subscriptions:all, billing_subscriptions:readonly List billing subscriptions.
create($start, $mode, $paymentConditions, $paymentMethod, $recurringRule, $customerId, $customerInvoiceData, $label = null) POST /billing_subscriptions billing_subscriptions:all Create a billing subscription that generates customer invoices on a recurring schedule.
get($billingSubscriptionId) GET /billing_subscriptions/{billingSubscriptionId} billing_subscriptions:all, billing_subscriptions:readonly Retrieve a billing subscription by its identifier.
update($billingSubscriptionId, $stop = null, ...) PUT /billing_subscriptions/{billingSubscriptionId} billing_subscriptions:all Update a billing subscription, including pausing or resuming it.
listInvoiceLineSections($billingSubscriptionId, $cursor = null, $limit = null, $sort = null) GET /billing_subscriptions/{billingSubscriptionId}/invoice_line_sections billing_subscriptions:all, billing_subscriptions:readonly List the invoice line sections of a billing subscription.
listInvoiceLines($billingSubscriptionId, $cursor = null, $limit = null, $sort = null) GET /billing_subscriptions/{billingSubscriptionId}/invoice_lines billing_subscriptions:all, billing_subscriptions:readonly List the invoice lines of a billing subscription.

Products ($client->products)

Manages the product catalog used to fill invoice, quote and billing subscription lines.

Method HTTP Scope Description
list($cursor = null, $limit = null, ...) GET /products products:readonly List products.
create($label, $priceBeforeTax, $vatRate, $description = null, ...) POST /products products:all Create a product.
get($productId) GET /products/{productId} products:readonly Retrieve a product by its identifier.
update($productId, $label = null, ...) PUT /products/{productId} products:all Update a product.

Example

<?php

declare(strict_types=1);

require __DIR__ . '/vendor/autoload.php';

use Pennylane\Sdk\Pennylane;
use Pennylane\Sdk\Filter;

$client = new Pennylane();

// Create a company customer.
$customer = $client->customers->companies->create(
    name: 'Acme Corp',
    billingAddress: [
        'address' => '12 rue de Rivoli',
        'postal_code' => '75004',
        'city' => 'Paris',
        'country_alpha2' => 'FR',
    ],
);

// Add a product to the catalog.
$product = $client->products->create(
    label: 'Consulting (half day)',
    priceBeforeTax: '450.00',
    vatRate: 'FR_200',
);

// Draft an invoice for that customer using the product, then finalize it.
$invoice = $client->customerInvoices->create(
    date: '2026-07-09',
    deadline: '2026-08-08',
    customerId: $customer->id,
    invoiceLines: [
        ['product_id' => $product->id, 'quantity' => '2'],
    ],
);

$finalized = $client->customerInvoices->finalize($invoice->id);

// List invoices created this month.
foreach ($client->customerInvoices->list(filter: Filter::gte('date', '2026-07-01')) as $inv) {
    echo $inv->id, "\n";
}