Repository navigation
Releases: factuarea/factuarea-node
Release list
v0.11.0
Minor Changes
-
#19
141b8c6Thanks @Chelu97! - Regenerate the SDK from the account model contract and expose it from the
client. This adds to the pendingcompany-axischangeset: both ship together in
the nextminor. Nothing here is published by this change.Breaking, in the same single window (axis-and-payload-breaking-window).
The account-model announcement will be at account-model.The claim voucher becomes the NIF transfer. Each of the three retired voucher
methods is listed next to the transfer method that replaces it:Retired Replaced by account.claimTokens.createaccount.nifTransfers.createaccount.claimTokens.listaccount.nifTransfers.listaccount.claimTokens.acceptaccount.nifTransfers.acceptaccount.nifTransfers.revokeis NEW: the voucher had no revoke method to replace.The only voucher left is
managedAccounts.claimTokens.create, which reissues the
voucher of a managed account (an addition of the contract, not a leftover).New client resources.
factuarea.companies(the account's NIF portfolio, with
stats) andfactuarea.managedAccounts(list,create,show,imports,
accessLevel,plan,managementandclaimTokens) are now properties of the
client, next toaccount.accountgainsnifTransfers,webhooks(with
deliveries),requestLogsandprovisioningUsage(). The bulk import
(managedAccounts.imports.createand.preview) takes aFormDataand is sent as
multipart/form-data; the SDK adds no JSON content type.The account argument is positional. Account-scoped methods take the account
idas their first argument, before any other id and before the body. TypeScript
callers get a compile error, but plain JavaScript callers would shift every
argument by one place WITHOUT an error: review each call toaccount.*,
companies.*andmanagedAccounts.*when upgrading.Webhook verification is unchanged:
factuarea.webhooks.verifyaccepts an account
envelope and returns it withaccount,account_relationshipandcompany_id
intact.Six
taxesmethods are removed, with no replacement (breaking): the contract
no longer declares them.TaxesResourcekeeps onlylistandshow; calling any
oftaxes.create,taxes.update,taxes.delete,taxes.setDefault,
taxes.setDefaultForDocumentortaxes.toggleis now a compile error in
TypeScript and aTypeErrorin plain JavaScript.Two verbs change with the document (breaking, same signatures):
contacts.restoregoes fromPATCHtoPOST(no othercontactsmethod
changes), andrecurringInvoices.updategoes fromPUTtoPATCH.Also new on the account axis, besides what is listed above:
account.members.show;account.members.grants.{list,show,update,delete};
account.invitations.show;account.apiKeys.updateNifScope(the API-key method
for the NIF scope); andcompanies.stats.Final axis contract, with the surfaces that landed on flat URLs in
0.8.0and
0.9.0. The 613-operation contract is regenerated:tasks,projects,
taskLabels,taskTimers,purchaseScans,purchaseScanEmails,notifications,
agenda,users,verifactu.representation,contacts.importsand
series.updatenow take the companyidas their first argument and hang off
/v1/companies/{company}/…. The scanner paths arepurchase-scans(hyphen).Every partial update is a
PATCH(breaking, same signatures): besides
recurringInvoices.update, theupdatemethods ofcontacts,products,
invoices,quotes,proformas,deliveryNotes,purchaseInvoices,series,
tasks,projects,webhookEndpoints,employees,workSchedules, absence
types and policies, andpurchaseScans.review, among others, stop usingPUT.
Money amounts in responses are decimal strings ("4.13"), not numbers.While the SDK is in
0.xa breaking change stays aminor;1.0.0remains
reserved for the API's GA (docs/VERSIONING.md). -
#19
03f0e9bThanks @Chelu97! - Regenerate the SDK from the company-axis contract: every company resource now
hangs off/v1/companies/{company}/…and the account surface off
/v1/accounts/{account}/…. 481 operations in 396 paths, up from 469 in 387
(+17 / −5).Breaking — every company-scoped method takes the company first. The company
stops being inferred in silence from the credential and travels in the URL, where
it is visible, logged and auditable:// Before await factuarea.invoices.list({ status: "paid" }); // Now await factuarea.invoices.list(company, { status: "paid" });
companyis the companyid— the onefactuarea.account.show()returns in
data.scope[].id— never its tax ID or its name.Also breaking, in the same single window:
factuarea.account.show()keeps its name and now answers on/v1/me,
returning the credential's scope (data.scope[]) alongside its API key.- The
X-Active-Profileheader is retired: the contract no longer declares it,
and the axis segment replaces it. - Updates use
PATCH(contacts.restore,contacts.updateCustomerProfile,
contacts.updateSupplierProfile,contacts.updateBankAccounts…), and amounts
travel as decimal strings. - The five API-key operations move from the company to the account axis:
companies.apiKeys.*→account.apiKeys.*on/v1/accounts/{account}/api-keys.
Added: the account axis (members and their module access, invitations, claim
tokens, owner transfer, usage),companies.issuingReadinessand
recurringInvoices.bulkStatus.Removed: the
ContactRoleV1Requesttype export. The role ofcontacts.assignContactRoletravels in the path (/contacts/{contact}/roles/{role}), so the operation no longer has a body.While the SDK is in
0.xa breaking change stays aminor;1.0.0remains
reserved for the API's GA (docs/VERSIONING.md).
v0.10.0
Minor Changes
-
#29
b88375bThanks @Chelu97! - Regenerate the SDK from an updated public OpenAPI spec
(+41 operations, -0 operations).Auto-generated by the Spec Sync workflow. While the SDK is in
0.x, a removed or renamed operation stays aminorand
1.0.0remains reserved for the API's GA (docs/VERSIONING.md).
Name the replacement of every removed operation here before merging. -
#29
b88375bThanks @Chelu97! - AddtransportDocumentsfor the transport control document (DeCA): list,
statuses, retrieve, create, update and delete drafts, issue, modify, close,
reopen, cancel, supersede, send, the evidence, and the PDF, QR and proof of
issuance downloads. ExportTransportDocument, its parts and the request type
of each step, and add theissue-transport-documentexample.qrnow returns aBinaryResponse: the resource generator treats every
image/*response as binary, so a PNG QR code keeps its bytes.
v0.9.0
Minor Changes
-
#25
8fab024Thanks @Chelu97! - Addseries.update(series, body?, config?)(PUT /v1/series/{series}, scopeseries:write) and re-pinspec/openapi.jsonfrom the current public contract (571 operations: 1 added, none removed).src/generated/andsrc/resources/are regenerated.New in the client:
series.updateedits a series with a partial body:name,code,counter_reset(never,annualormonthly),number_format,initial_number,invoice_kindand the deprecatedyear_reset.document_typeis not editable. It answers the updatedSeries. The new typeUpdateSeriesRequestis exported from@factuarea/sdk.- Each fiscal guard of the numbering arrives as
ValidationErrorwithcodebusiness_rule_violationand asubcode:series_code_immutable_with_documents,series_format_immutable_with_documents,series_locked_by_verifactu,series_initial_number_creates_gap,series_invoice_kind_lockedandseries_default_kind_change. Invalid values answerparameter_invalid_value. - Changing only
counter_resetalso emits the webhookseries.updated.PATCHandDELETEon a series keep answering405series_immutable, now withAllow: GET, PUT; archive a series instead of deleting it. invoices.activitiespublishes moreevent_typevalues with an exactmetadatacontract: the result of each AEAT submission (verifactu.record_accepted,verifactu.record_rejected,verifactu.transmission_failed,verifactu.transmission_blocked),invoice.email_failed,invoice.public_link_viewedand the payment eventspayment.payment_created,payment.payment_reversedandpayment.payment_updated, whoseprovideris the gateway (stripe,gocardless,monei,woocommerceorshopify) ornullfor a manual payment.VeriFactuRecordgains the requiredaeat_warning_requires_subsanation(boolean | null). Code that buildsVeriFactuRecordobjects by hand, such as test fixtures typed asVeriFactuRecord, must add it.
-
#25
dab5844Thanks @Chelu97! - Add unattended checkout (self-service kiosks and vending machines) and the VERI*FACTU remission controls, and re-pinspec/openapi.jsonfrom the current public contract (570 operations: 6 added, none removed).src/generated/andsrc/resources/are regenerated.New in the client:
invoices.createissues a paid simplified invoice in one idempotent call. The request acceptstype(F1orF2),prices_include_tax,payment(method,paid_at,reference),operation_onand the optionsregister_verifactuandwait_for_pdf;client_idis optional, so anF2without it is an anonymous ticket. The response is the newInvoiceWithCheckoutBlockstype: the invoice plusverifactu(statusregisteredorfailed,error_code,aeat_status,huella,qr_url,qr_png_base64,legend,csv),pdf(status, signedurl,expires_at) andpublic_url.- A late retry with the same
external_idanswers200withIdempotent-Replayed: trueand the invoice already issued.invoices.createreturns the same body for201and200; callfactuarea.http.requestwhen you need the status or the header. A different type or total answers409idempotency_key_reusedwith subcodeunattended_replay_mismatch, and a request still in flight answers409resource_locked; both arrive asConflictErrorwithcode,subcodeandparam. invoices.pdfandinvoices.pdfLinkacceptformat:a4(default),ticket_80orticket_58.invoices.pdfLink(invoice, params?, config?)keeps the previousinvoices.pdfLink(invoice, config?)call working: a second argument made only of request-option keys (headers,timeout,maxRetries,idempotencyKey) is still read as the options, and any other object is the query.invoices.annulacceptsrevert_collections, which reverts every live payment (reasonissued_in_error) and annuls the invoice atomically.invoices.canAnnulalso returnsrequires_collection_reversalandactive_collections_amount.invoices.correctivelines acceptunit,regime_key,exemption_reasonandexemption_reason_text; an omitted value is inherited from the original line. The conversion of a quote, a proforma or a delivery note can returnwarningsandwarning_codes(zero_rate_line_without_exemption).Invoicegainsoperation_on.- Series carry a purpose:
Series.invoice_kindiscomplete,simplified,correctiveorsimplified_corrective, andnullfor a series that is not of invoices.series.createacceptsinvoice_kind.series.list,series.defaultandseries.activeaccept aninvoice_kindfilter, andseries.activealso takesdocument_type;series.active(params?, config?)keeps theseries.active(config?)call working with the same rule asinvoices.pdfLink. series_idis optional and nullable ininvoices.create.invoices.updateacceptstype(F1orF2).invoices.correctiveacceptscorrection_nature(IorS) andseries_id.invoices.duplicateandseries.activedocument a422response.contacts.imports.showretrieves a contact import (BusinessContactImport), andcontacts.imports.errorsdownloads its errors as CSV and returns aBinaryResponse.BusinessContactImportPreviewgainsimport_uuid,added_count,skipped_count,failed_count,unprocessed_count,statusandfailure_reason, so code that builds that type by hand must add them; its rows gain an optionalresult.- The types
BusinessContactImport,CreateCorrectiveInvoiceRequest,CreateSeriesRequestandUpdateInvoiceRequestare exported from@factuarea/sdk. verifactu.records.retryBlockedreactivates every blocked record at once.VeriFactuRecordgainsaeat_error_code,is_blocked,block_reasonandcan_subsanar, andverifactu.records.subsanarnow returns the id of the new record.VeriFactuStatsgainspending_incident_count,blocked_incident_countandoldest_pending_at.verifactu.representation(show,register,revoke) manages the representation that enables remission by a third party.VeriFactuConfiggainsremission_modeand theactive_representation_*fields, andverifactu.settingsacceptsremission_mode.FactuareaError.lineIndexcarrieserror.line_index, the zero-based position of the document line a domain rule rejected, theNoflines.N.tax_rate. It isnullfor any other error.- The types
CreateInvoiceRequest,InvoiceWithCheckoutBlocks,AnnulInvoiceV1Request,CanAnnulInvoice,CompanyRepresentation,RegisterCompanyRepresentationV1Request,RemissionMode,RepresentationKind,VeriFactuConfig,VeriFactuRecordandVeriFactuStatsare exported from@factuarea/sdk.
Breaking changes (the SDK is in
0.x, so they land in a minor):- A sale line with no
tax_rate, no referenced tax and no product with a tax no longer receives an implicit 21 %. It takes the company's default VAT for the document, or the request is rejected with 422missing_required_param,paramlines.N.tax_rateandline_indexN. - Operations that issue an invoice (
invoices.createwhen it issues,issue,corrective,substituteSimplified, andsendandmarkSentwhen they issue) can answer 422verifactu_not_eligiblewhen a field does not fit the AEAT billing record: a customer name over 120 characters, a Spanish tax ID that is not 9 characters, an invoice number with characters the AEAT does not accept, or more than 12 tax breakdowns.error.paramsays which (client_id,series_id,original_invoice_id,simplified_invoice_uuids,company_name,lines,totalortype). No number is consumed and the invoice stays as it was, so correct the data and repeat. InbulkCreateandbulkStatusthe rejection appears per element infailures. - Issuing and annulling (
annul,void) answer 422verifactu_not_eligiblewith subcodesigning_certificate_unavailablefor a company that has enabled VeriFactu in NO VERIFACTU mode and has no usable certificate, until one is uploaded.error.paramiscertificate,representationorsystem_certificate. Companies with VeriFactu disabled and companies in VERIFACTU mode are not affected. verifactu.records.retryno longer answersmax_retries_exceeded: a record is retried without a cap while the incident lasts.Invoicegains the requiredoperation_on(string | null). Code that buildsInvoiceobjects by hand, such as test fixtures typed asInvoice, must add it.- The payment reversal reason gains
issued_in_errorinInvoicePaymentDetail.reversal_reasonand in thepayment.reversedevent, so an exhaustiveswitchover it needs a new case. It cannot be requested for a single payment withpaymentsRevert.
v0.8.0
Minor Changes
-
#22
cd19eddThanks @Chelu97! - Add the tasks and projects resources and re-pinspec/openapi.jsonfrom the current public contract (457 paths / 564 operations: 81 added, none removed).src/generated/andsrc/resources/are regenerated.New resources on the client (80 operations). Every write sends an
Idempotency-Key, lists return aPagewith cursor auto-pagination, and errors use the typed hierarchy.factuarea.projects(22):list,create,show,update,delete,archive,unarchive,findByKey;columns(list,create,update,delete,reorder);customFields(list,create,update,delete);tasks(export,import);timeSummary.show;timeInvoices(preview,create).columns.deletetakesmove_to_column_idin its query to relocate the column's tasks.factuarea.tasks(45):search,create,show,update,delete,duplicate,findByKey,linked,status,move,reposition,assign,unassign,bulkStatus,bulkUpdate,bulkDelete;comments(list,create,update,delete);relations(list,create,delete);labels(assign,unassign);customFields.set;externalLinks(list,create,delete);entityLinks(list,create,delete);attachments(list,show,create,download,delete);uploadLinks.create;timeEntries(list,show,create,update,delete);timer.start;activities.list.createacceptsentity_linkto link the task to a document or contact in the same call, andcustom_fieldsis a map from field id to a string, number, boolean, string array ornull.factuarea.taskLabels(5):list,create,show,update,delete.factuarea.taskTimers(2):current({ data: null }when nothing is running) andstop.factuarea.users(2):me,list.factuarea.notifications(3):list,read,markAllRead.factuarea.agenda(1):list, a combined agenda of due tasks, document due dates, tax deadlines, absences and holidays.
The request and response types of these resources (
Project,ProjectColumn,Task,TaskComment,TaskLabel,TaskTimeEntry,TaskAttachment,AgendaItem,CreateTaskV1Request,UpdateTaskV1Request,LogTaskTimeV1Requestand the rest) are exported from@factuarea/sdk.Also carried by the re-pin, measured against the previous pinned spec:
- New
invoices.issue(POST /invoices/{invoice}/issue). Invoicegainsissued_at,sent_viaandis_sent, itsstatusis now a typed union, andinvoices.listaccepts anis_sentfilter.- Recurring invoices gain
generation_mode(draft,issueorissue_and_send) on create, update and read. - 24 new webhook event types, accepted by
webhookEndpointssubscriptions and test events:invoice.issued,invoice.marked_sent,invoice.unsentand 21 for tasks, comments, time entries and projects. - New enum values:
issuedin the bulk invoice status change,issuedin place ofsentin the invoice Excel export status filter,issuein place ofdraftas a scheduled invoice action, and the automation action typescreate_task,change_task_status,assign_taskandadd_task_comment. - API key scopes:
projects:read|write|delete,tasks:read|write|delete,users:readandnotifications:read|writeare added; the retiredclients:*andsuppliers:*scopes leave the enum.
v0.7.0
Minor Changes
-
#12
4c2ee4dThanks @fernandoc00! - Add purchase scanner resources and extraction/review types from the backend contract. Support batch uploads, source downloads, versioned review and draft conversion, duplicate resolution, archive/restore, and inbound email history. Preserve structured batch failures and request options across pagination.Fix the default request-version header to the supported stable version
2026-06-01; the previous export-date pin was rejected by the backend. -
#12
396bf15Thanks @fernandoc00! - Re-pinspec/openapi.jsonfrom the current backend contract (399 paths / 483 operations) and regeneratesrc/generated/andsrc/resources/.BREAKING: the backend retired the legacy
clients/suppliersroutes (replaced bycontacts, which already covers the same identities and roles).ClientsResource,SuppliersResource, thefactuarea.clients/factuarea.suppliersclient properties and theSuppliertype export are removed; the SDK stays in0.x(breaking changes may land in a minor while pre-GA,docs/VERSIONING.md), so this is aminor, not amajor, release. Usecontactsfor every identity, role and profile operation.Harden
scripts/build-resources.mjs(design D4): operations withoutx-speakeasy-groupnow fail the generator with a listing ofmethod path operationIdbefore any output is written, instead of being silently dropped. The script also accepts--spec <path>/--out <dir>for testing against fixture specs.Add spec-guided
Idempotency-Keysupport (design D6):_send/_deleteinsrc/core/resource.tsaccept an optional fifth{ idempotent?: boolean }argument, and the generator sets it for non-POSTmutations the spec marks as requiring the header.src/core/http-client.ts'sMETHODS_WITH_IDEMPOTENCYalready generates the header unconditionally for everyPOST/PUT/PATCH/DELETE(a broader policy than D6, already shipped on this branch before this change) — that blanket behavior is kept as-is per the repo owner's instruction, so this is additive, not a narrowing.Method names follow
backend/docs/api/sdk-method-naming.md @ 1.1.0(up from the1.0.0cited by the generator before this change; the naming rule itself did not change).
v0.6.0
Minor Changes
-
#16
90f936cThanks @Chelu97! - Regenerate the SDK from the public OpenAPI spec that publishes contacts as the
sole identity resource (+9 operations, -28 operations; 469 in total).Removed: the
clientsandsuppliersresources, retired from the public API on
2026-09-16 (/v1/clients/*and/v1/suppliers/*), plus theSuppliertype.
Replacements, all onfactuarea.contacts(filter byroles: ["customer"]or
roles: ["supplier"]where the legacy resource implied the role):clients.list|search|show|create|update|deleteandsuppliers.*→contacts.list|search|show|create|update|deleteclients.stats/suppliers.stats→contacts.statsclients.activities/suppliers.activities→contacts.activitiesclients.bulkCreate→contacts.bulkCreate;clients.bulkDelete/suppliers.bulkDelete→contacts.bulkDeleteclients.import/clients.importTemplate→contacts.import/contacts.importTemplateclients.censusVerification→contacts.verifyCensusclients.findByTaxId/suppliers.findByTaxId→contacts.findByTaxIdclients.findByExternalId/suppliers.findByExternalId→contacts.findByExternalIdsuppliers.bulkStatus→contacts.bulkChangeContactRoleStatussuppliers.toggleActive→contacts.changeContactRoleStatus
Added on
contacts:stats,activities,bulkCreate,bulkDelete,
importTemplate,verifyCensus,findByTaxId,findByExternalIdand
archive.While the SDK is in
0.xa removed operation is aminor;1.0.0stays
reserved for the API's GA (docs/VERSIONING.md).
v0.5.0
Minor Changes
-
#13
ecf8c54Thanks @fernandoc00! - Export the canonical contact and request types, make contacts the default in examples and documentation, and mark legacy client/supplier projections as compatibility resources. Cover contact role, profile, import and archive/restore operations against the public contract.Preserve per-request headers (including the active company profile), timeouts and abort signals across paginated requests. Encode boolean query filters as 0/1 for Laravel validation and expose import mappings as named-column objects instead of arrays.
v0.4.0
Minor Changes
- #10
271b9f7Thanks @fernandoc00! - Add canonical contacts, contact roles and preferences, and preserve array filters in Laravel-compatible query parameters.
v0.3.1
Patch Changes
- #7
25619eaThanks @Chelu97! -products.variants.update:stockno longer declaresminimum: 0. Send the current balance to leave it untouched (it may be negative when delivered documents ran ahead of the incoming stock); any other value is a manual set and must still be>= 0(422 otherwise).products.variants.createkeepsminimum: 0.
v0.3.0
Minor Changes
-
#5
53510b2Thanks @Chelu97! - Regenerate the SDK from the public OpenAPI spec published with Factuarea v1.15.26
(+57 operations, -0 operations): the automation engine (client.automations.*,
18 operations), ecommerce stores, product options and configurations, price-list
resolution and stock-ledger audit.The resource generator now nests namespaces to any depth
(client.automations.rules.versions.list()), which the three-level
automations.rules.versionsandautomations.runs.stepsgroups require: with
two levels their methods collided withrules.list/runs.list.