diff --git a/app/Filters/ClientFilters.php b/app/Filters/ClientFilters.php index 94eb646e43..df9a2cb860 100644 --- a/app/Filters/ClientFilters.php +++ b/app/Filters/ClientFilters.php @@ -152,21 +152,6 @@ class ClientFilters extends QueryFilters }); - // return $this->builder->where(function ($query) use ($filter) { - // $query->where('name', 'like', '%'.$filter.'%') - // ->orWhere('id_number', 'like', '%'.$filter.'%') - // ->orWhere('number', 'like', '%'.$filter.'%') - // ->orWhereHas('contacts', function ($query) use ($filter) { - // $query->where('first_name', 'like', '%'.$filter.'%'); - // $query->orWhere('last_name', 'like', '%'.$filter.'%'); - // $query->orWhere('email', 'like', '%'.$filter.'%'); - // $query->orWhere('phone', 'like', '%'.$filter.'%'); - // }) - // ->orWhere('custom_value1', 'like', '%'.$filter.'%') - // ->orWhere('custom_value2', 'like', '%'.$filter.'%') - // ->orWhere('custom_value3', 'like', '%'.$filter.'%') - // ->orWhere('custom_value4', 'like', '%'.$filter.'%'); - // }); } /** diff --git a/openapi/api-docs.yaml b/openapi/api-docs.yaml index 1f7bedc2cd..e966738909 100644 --- a/openapi/api-docs.yaml +++ b/openapi/api-docs.yaml @@ -179,7 +179,7 @@ paths: label: curl source: | curl --request POST \ - --url 'https://invoicing.co/api/v1/login?include=company,token' \ + --url 'https://demo.invoiceninja.com/api/v1/login?include=company,token' \ --header 'X-API-TOKEN: YOUR_API_TOKEN_HERE' \ --header 'X-Requested-With: XMLHttpRequest' \ --header 'Accept: application/json' @@ -12704,7 +12704,12 @@ paths: label: php source: | $ninja = new InvoiceNinja("your_token"); - $invoices = $ninja->clients->all(); + $invoices = $ninja->clients->all([ + 'balance' => 'lt:10', // get all clients with a balance less than 10 + 'per_page' => 10, // return 10 results per page + 'page' => 2, // paginate to page 2 + 'include' => 'documents', // include the documents relationship + ]); - lang: curl label: curl source: | @@ -12756,64 +12761,146 @@ paths: - $ref: "#/components/parameters/updated_at" - $ref: "#/components/parameters/is_deleted" - $ref: "#/components/parameters/filter_deleted_clients" - - $ref: "#/components/parameters/vendor_id" - name: name in: query - description: Filter by client name + description: | + Filter by client name + + ```html + ?name=bob + ``` required: false schema: type: string example: bob - name: balance in: query - description: Filter by client balance, format uses an operator and value separated by a colon. lt,lte, gt, gte, eq + description: | + Filter by client balance, format uses an operator and value separated by a colon. lt,lte, gt, gte, eq + + ```html + ?balance=lt:10 + ``` + + ie all clients whose balance is less than 10 required: false schema: type: string example: lt:10 - name: between_balance in: query - description: Filter between client balances, format uses two values separated by a colon + description: | + Filter between client balances, format uses two values separated by a colon + + ```html + ?between_balance=10:100 + ``` required: false schema: type: string example: 10:100 - name: email in: query - description: Filter by client email + description: | + Filter by client email + + ```html + ?email=bob@gmail.com + ``` required: false schema: type: string example: bob@gmail.com - name: id_number in: query - description: Filter by client id_number + description: | + Filter by client id_number + + ```html + ?id_number=0001 + ``` required: false schema: type: string example: a1039883 - name: number in: query - description: Filter by client number + description: | + Filter by client number + + ```html + ?number=0002 + ``` required: false schema: type: string example: a1039883 - name: filter in: query - description: Filters clients on columns - name, id_number, contact.first_name contact.last_name, contact.email, custom_value1-4 + description: | + Broad filter which targets multiple client columns: + + ```html + name, + id_number, + contact.first_name + contact.last_name, + contact.email, + contact.phone + custom_value1, + custom_value2, + custom_value3, + custom_value4, + ``` + + ```html + ?filter=Bobby + ``` required: false schema: type: string example: a1039883 - name: sort in: query - description: Returns the list sorted by column in ascending or descending order. + description: | + Returns the list sorted by column in ascending or descending order. + + Ensure you use column | direction, ie. + + ```html + ?sort=id|desc + ``` required: false schema: type: string example: id|desc name|desc balance|asc + - name: group + in: query + description: | + Returns the list of clients assigned to {group_id} + + ```html + ?group=X89sjd8 + ``` + required: false + schema: + type: string + example: X89sjd8 + + - name: client_id + in: query + description: | + Returns the list of clients with {client_id} - proxy call to retrieve a client_id wrapped in an array + + ```html + ?client_id=X89sjd8 + ``` + required: false + schema: + type: string + example: X89sjd8 + responses: 200: description: 'A list of clients' @@ -12845,12 +12932,58 @@ paths: description: | Adds a client to a company + > 🚨 Important When creating (or updating) a client you must include the child contacts with all mutating requests. Client contacts cannot be modified in isolation. - + x-codeSamples: + - lang: php + label: php + source: | + $ninja = new InvoiceNinja("YOUR-TOKEN"); + + $client = $ninja->clients->create([ + 'name' => 'Client Name', + 'contacts' => [ + [ + 'first_name' => 'John', + 'last_name' => 'Smith', + 'email' => 'john@example.com', + 'phone' => '555-0123' + ] + ], + 'address1' => '123 Main St', + 'city' => 'New York', + 'state' => 'NY', + 'postal_code' => '10001', + 'country_id' => '1' + ]); + - lang: curl + label: curl + source: | + curl -X POST https://demo.invoiceninja.com/api/v1/clients \ + -H "X-API-TOKEN: YOUR-TOKEN" \ + -H "Content-Type: application/json" \ + -H "X-Requested-With: XMLHttpRequest" \ + -d '{ + "name": "Client Name", + "contacts": [ + { + "first_name": "John", + "last_name": "Smith", + "email": "john@example.com", + "phone": "555-0123" + } + ], + "address1": "123 Main St", + "city": "New York", + "state": "NY", + "postal_code": "10001", + "country_id": "1" + }' operationId: storeClient parameters: - $ref: '#/components/parameters/X-API-TOKEN' - $ref: '#/components/parameters/X-Requested-With' + - $ref: '#/components/parameters/index' - $ref: '#/components/parameters/client_include' requestBody: description: Client object that needs to be added to the company @@ -12889,10 +13022,24 @@ paths: - clients summary: 'Show client' description: 'Displays a client by id' + x-codeSamples: + - lang: php + label: php + source: | + $ninja = new InvoiceNinja("YOUR-TOKEN"); + $client = $ninja->clients->show('clientId123'); + - lang: curl + label: php + source: | + curl -X GET https://demo.invoiceninja.com/api/v1/clients/clientId123 \ + -H "X-API-TOKEN: YOUR-TOKEN" \ + -H "X-Requested-With: XMLHttpRequest" + operationId: showClient parameters: - $ref: '#/components/parameters/X-API-TOKEN' - $ref: '#/components/parameters/X-Requested-With' + - $ref: '#/components/parameters/index' - $ref: '#/components/parameters/client_include' - name: id in: path @@ -12930,11 +13077,50 @@ paths: tags: - clients summary: 'Update client' - description: 'Handles the updating of a client by id' + description: | + Handles the updating of a client by id + + > 🚨 Important + When creating (or updating) a client you must include the child contacts with all mutating requests. Client contacts cannot be modified in isolation. + + x-codeSamples: + - lang: php + label: php + source: | + $ninja = new InvoiceNinja("YOUR-TOKEN"); + $client = $ninja->clients->update('clientId123', [ + 'name' => 'Updated Name', + 'contacts' => [ + [ + 'first_name' => 'John', + 'last_name' => 'Smith', + 'email' => 'john@example.com' + ] + ] + ]); + - lang: curl + label: curl + source: | + curl -X PUT https://demo.invoiceninja.com/api/v1/clients/clientId123 \ + -H "X-API-TOKEN: YOUR-TOKEN" \ + -H "Content-Type: application/json" \ + -H "X-Requested-With: XMLHttpRequest" \ + -d '{ + "name": "Updated Name", + "contacts": [ + { + "first_name": "John", + "last_name": "Smith", + "email": "john@example.com" + } + ] + }' + operationId: updateClient parameters: - $ref: '#/components/parameters/X-API-TOKEN' - $ref: '#/components/parameters/X-Requested-With' + - $ref: '#/components/parameters/index' - $ref: '#/components/parameters/client_include' - name: id in: path @@ -12979,11 +13165,32 @@ paths: tags: - clients summary: 'Delete client' - description: 'Handles the deletion of a client by id' + description: | + Handles the deletion of a client by id + + > ❗ Note + Deleting a client does not purge the client from the system. The delete action will remove the clients data from all + views in the application but keep it all on file. A Client can be laterrestored reversing this action. To permanently wipe a client and + all of their records from the system, use the /purge route + + x-codeSamples: + - lang: php + label: php + source: | + $ninja = new InvoiceNinja("YOUR-TOKEN"); + $ninja->clients->delete('clientId123'); + - lang: curl + label: curl + source: | + curl -X DELETE https://demo.invoiceninja.com/api/v1/clients/clientId123 \ + -H "X-API-TOKEN: YOUR-TOKEN" \ + -H "X-Requested-With: XMLHttpRequest" + operationId: deleteClient parameters: - $ref: '#/components/parameters/X-API-TOKEN' - $ref: '#/components/parameters/X-Requested-With' + - $ref: '#/components/parameters/index' - $ref: '#/components/parameters/client_include' - name: id in: path @@ -13023,7 +13230,8 @@ paths: parameters: - $ref: '#/components/parameters/X-API-TOKEN' - $ref: '#/components/parameters/X-Requested-With' - - $ref: '#/components/parameters/include' + - $ref: '#/components/parameters/index' + - $ref: '#/components/parameters/client_include' - name: id in: path description: 'The Client Hashed ID' @@ -13066,6 +13274,7 @@ paths: parameters: - $ref: '#/components/parameters/X-API-TOKEN' - $ref: '#/components/parameters/X-Requested-With' + - $ref: '#/components/parameters/index' - $ref: '#/components/parameters/client_include' responses: 200: @@ -13132,12 +13341,33 @@ paths: - custom_value2 - custom_value3 - custom_value4 - + + x-codeSamples: + - lang: php + label: php + source: | + $ninja = new InvoiceNinja("YOUR-TOKEN"); + $ninja->clients->bulk([ + 'action' => 'archive', + 'ids' => ['clientId1', 'clientId2'] + ]); + - lang: curl + label: curl + source: | + curl -X POST https://demo.invoiceninja.com/api/v1/clients/bulk \ + -H "X-API-TOKEN: YOUR-TOKEN" \ + -H "Content-Type: application/json" \ + -H "X-Requested-With: XMLHttpRequest" \ + -d '{ + "action": "archive", + "ids": ["clientId1", "clientId2"] + }' operationId: bulkClients parameters: - $ref: '#/components/parameters/X-API-TOKEN' - $ref: '#/components/parameters/X-Requested-With' - $ref: '#/components/parameters/index' + - $ref: '#/components/parameters/client_include' requestBody: description: 'Bulk action array' required: true @@ -13176,10 +13406,26 @@ paths: - clients summary: 'Add client document' description: 'Handles the uploading of a document to a client, please note due to a quirk in REST you will need to use a _method parameter with value of POST' + x-codeSamples: + - lang: php + label: php + source: | + $ninja = new InvoiceNinja("YOUR-TOKEN"); + $ninja->clients->upload('clientId123', '/path/to/document.pdf'); + - lang: curl + label: curl + source: | + curl -X POST https://demo.invoiceninja.com/api/v1/clients/clientId123/upload \ + -H "X-API-TOKEN: YOUR-TOKEN" \ + -H "X-Requested-With: XMLHttpRequest" \ + -F "_method=POST" \ + -F "documents[]=@/path/to/document.pdf" + operationId: uploadClient parameters: - $ref: '#/components/parameters/X-API-TOKEN' - $ref: '#/components/parameters/X-Requested-With' + - $ref: '#/components/parameters/index' - $ref: '#/components/parameters/client_include' - name: id in: path @@ -13199,10 +13445,24 @@ paths: _method: type: string example: POST - documents: + documents[]: type: array + description: | + Array of files to upload. The files should be sent with the key name 'documents[]'. + + Supported file types: + - PDF (.pdf) + - Word (.doc, .docx) + - Excel (.xls, .xlsx) + - Images (.jpg, .jpeg, .png) + - Text (.txt) + + Maximum file size: 20MB per file items: + type: string format: binary + description: The file contents + example: "@/path/to/document.pdf" responses: 200: description: 'Returns the client object' @@ -13235,15 +13495,28 @@ paths: description: | Handles purging a client. - Please note this is a destructive action. - + > ❗ Note + This is a destructive action. This action will remove all data associated with the client and cannot be undone. + x-codeSamples: + - lang: php + label: php + source: | + $ninja = new InvoiceNinja("YOUR-TOKEN"); + $ninja->clients->purge('clientId123'); + - lang: curl + label: curl + source: | + curl -X POST https://demo.invoiceninja.com/api/v1/clients/clientId123/purge \ + -H "X-API-TOKEN: YOUR-TOKEN" \ + -H "X-Requested-With: XMLHttpRequest" \ + -H "X-API-PASSWORD: YOUR-PASSWORD" + operationId: purgeClient parameters: - $ref: '#/components/parameters/X-API-TOKEN' - $ref: '#/components/parameters/X-Requested-With' - $ref: '#/components/parameters/X-API-PASSWORD' - - $ref: '#/components/parameters/client_include' - name: id in: path description: 'The Client Hashed ID' @@ -13283,12 +13556,30 @@ paths: The id parameter is the client that will be the primary client after the merge has completed. The mergeable_client_hashed_id is the client that will be merged into the primary client, this clients records will be updated and associated with the primary client. + + > 🚨 **Important** + This action requires elevated permissions, please note the X-API-PASSWORD header requirements for this route. + + x-codeSamples: + - lang: php + label: php + source: | + $ninja = new InvoiceNinja("YOUR-TOKEN"); + $ninja->clients->merge('primaryClientId', 'mergeableClientId'); + - lang: curl + label: curl + source: | + curl -X POST https://demo.invoiceninja.com/api/v1/clients/primaryClientId/mergeableClientId/merge \ + -H "X-API-TOKEN: YOUR-TOKEN" \ + -H "X-Requested-With: XMLHttpRequest" + operationId: mergeClient parameters: - $ref: '#/components/parameters/X-API-TOKEN' - $ref: '#/components/parameters/X-Requested-With' - - $ref: '#/components/parameters/client_include' - $ref: '#/components/parameters/X-API-PASSWORD' + - $ref: '#/components/parameters/index' + - $ref: '#/components/parameters/client_include' - name: id in: path description: 'The Client Hashed ID' @@ -13332,10 +13623,37 @@ paths: summary: 'Client statement PDF' description: 'Return a PDF of the client statement' operationId: clientStatement + x-codeSamples: + - lang: php + label: php + source: | + $ninja = new InvoiceNinja("YOUR-TOKEN"); + $statement = $ninja->clients->statement([ + 'client_id' => 'clientId123', + 'start_date' => '2024-01-01', + 'end_date' => '2024-12-31', + 'show_payments_table' => true, + 'show_aging_table' => true + ]); + - lang: curl + label: curl + source: | + curl -X POST https://demo.invoiceninja.com/api/v1/client_statement \ + -H "X-API-TOKEN: YOUR-TOKEN" \ + -H "Content-Type: application/json" \ + -H "X-Requested-With: XMLHttpRequest" \ + -d '{ + "client_id": "clientId123", + "start_date": "2024-01-01", + "end_date": "2024-12-31", + "show_payments_table": true, + "show_aging_table": true + }' parameters: - $ref: '#/components/parameters/X-API-TOKEN' - $ref: '#/components/parameters/X-Requested-With' - - $ref: '#/components/parameters/include' + - $ref: '#/components/parameters/index' + - $ref: '#/components/parameters/client_include' requestBody: description: 'Statement Options' required: true @@ -13398,7 +13716,8 @@ paths: parameters: - $ref: '#/components/parameters/X-API-TOKEN' - $ref: '#/components/parameters/X-Requested-With' - - $ref: '#/components/parameters/include' + - $ref: '#/components/parameters/index' + - $ref: '#/components/parameters/client_include' - name: bounce_id in: path description: 'The postmark Bounce ID reference' @@ -13441,7 +13760,8 @@ paths: parameters: - $ref: '#/components/parameters/X-API-TOKEN' - $ref: '#/components/parameters/X-Requested-With' - - $ref: '#/components/parameters/include' + - $ref: '#/components/parameters/index' + - $ref: '#/components/parameters/client_include' - name: client in: path description: 'The Client Hashed ID reference' @@ -14705,7 +15025,21 @@ components: client_include: name: include in: query - description: Include child relationships of the Client Object. + description: | + Include child relationships of the Client Object. ie ?include=documents,system_logs + + ```html + Available includes: + + contacts [All contacts related to the client] + documents [All documents related to the client] + gateway_tokens [All payment tokens related to the client] + activities [All activities related to the client] + ledger [The client ledger] + system_logs [System logs related to the client] + group_settings [The group settings object the client is assigned to] + + ``` required: false schema: type: string @@ -14858,7 +15192,24 @@ components: index: name: index in: query - description: 'Replaces the default response index from data to a user specific string' + description: | + Replaces the default response index from data to a user specific string + + ie. + + ```html + ?index=new_index + ``` + + response is wrapped + + ```json + { + 'new_index' : [ + ..... + ] + } + ``` required: false schema: type: string @@ -14881,6 +15232,11 @@ components: - active - archived - deleted + + ```html + GET /api/v1/invoices?status=archived,deleted + Returns only archived and deleted invoices + ``` required: false schema: type: string @@ -14890,6 +15246,11 @@ components: in: query description: | Filters the entity list by client_id. Suitable when you only want the entities of a specific client. + + ```html + GET /api/v1/invoices?client_id=AxB7Hjk9 + Returns only invoices for the specified client + ``` required: false schema: type: string @@ -14899,6 +15260,11 @@ components: in: query description: | Filters the entity list by the created at timestamp. Parameter value can be a datetime string or unix timestamp + + ```html + GET /api/v1/invoices?created_at=2022-01-10 + Returns entities created on January 10th, 2022 + ``` required: false schema: type: integer @@ -14908,6 +15274,11 @@ components: in: query description: | Filters the entity list by the updated at timestamp. Parameter value can be a datetime string or unix timestamp + + ```html + GET /api/v1/invoices?updated_at=2022-01-10 + Returns entities last updated on January 10th, 2022 + ``` required: false schema: type: integer @@ -14917,6 +15288,11 @@ components: in: query description: | Filters the entity list by entities that have been deleted. + + ```html + GET /api/v1/invoices?is_deleted=true + Returns only soft-deleted entities + ``` required: false schema: type: boolean @@ -14926,6 +15302,11 @@ components: in: query description: | Filters the entity list by an associated vendor + + ```html + GET /api/v1/purchases?vendor_id=AxB7Hjk9 + Returns only purchases for the specified vendor + ``` required: false schema: type: string @@ -14935,12 +15316,16 @@ components: in: query description: | Filters the entity list and only returns entities for clients that have not been deleted + + ```html + GET /api/v1/invoices?filter_deleted_clients=true + Returns only invoices for active (non-deleted) clients + ``` required: false schema: type: string example: ?filter_deleted_clients=true ########################### Generic filters available across all filter ################################## - schemas: CreditPaymentable: properties: @@ -20071,11 +20456,11 @@ components: name: description: 'The name of the client company or organization' type: string - example: "Jim's Housekeeping" + example: "Bob & Co Housekeeping" website: description: 'The website URL of the client company or organization' type: string - example: 'https://www.jims-housekeeping.com' + example: 'https://www.boandco-housekeeping.com' private_notes: description: 'Notes that are only visible to the user who created the client' type: string @@ -20113,7 +20498,10 @@ components: type: string example: '555-3434-3434' country_id: - description: "The unique identifier of the client's country" + description: | + The unique identifier of the client's country expressed by the countries ISO number. + + Optionally, instead of the country_id you can pass either the iso_3166_2 or iso_3166_3 country code into the country_code property. type: number format: integer example: '1' @@ -20165,7 +20553,10 @@ components: type: string example: '6110' shipping_country_id: - description: "The unique identifier of the country for the client's shipping address" + description: | + The unique identifier of the client's shipping country expressed by the countries ISO number. + + Optionally, instead of the shipping_country_id you can pass either the iso_3166_2 or iso_3166_3 country code into the shipping_country_code property. type: number format: integer example: '4' @@ -22203,11 +22594,31 @@ tags: ```html /api/v1/login?include=company,user ``` + - name: clients x-displayName: Clients - - # description: | - # Endpoint definitions for interacting with clients. + description: | + The Clients API provides endpoints for managing client records within your company. A client represents a customer + or business entity that you provide services or products to. + + ## Key Features + - Create, read, update, and delete client records + - Manage client contact information and billing details + - View client-specific transaction history + - Handle multiple contacts per client + - Track client-specific settings and preferences + + ## Client Statuses + - Active: Client is currently active and can be billed + - Archived: Client is archived and hidden from active lists + - Deleted: Client is marked for deletion but retained in the database + + ## Best Practices + - Always validate client email addresses + - Use unique client numbers for easy reference + - Keep contact information up to date + - Set appropriate client-specific currency and tax settings + - name: products x-displayName: Products description: | @@ -22247,7 +22658,7 @@ tags: Endpoint definitions for interacting with payments. - name: quotes - x-displayName:: Quotes + x-displayName: Quotes description: | Endpoint definitions for interacting with quotes. @@ -22295,9 +22706,18 @@ tags: x-displayName: Reports description: | Endpoint definitions for interacting with reports. - + externalDocs: - description: "https://invoiceninja.github.io" - url: "https://invoiceninja.github.io" + description: "Client Libraries" + x-libraries: + - name: PHP SDK + description: Official PHP client library + url: https://github.com/invoiceninja/sdk-php + packageUrl: https://packagist.org/packages/invoiceninja/sdk-php + language: PHP + - name: User Guide + description: Official user guide + url: https://invoiceninja.github.io + security: - ApiKeyAuth: [] diff --git a/openapi/components/parameters.yaml b/openapi/components/parameters.yaml index 8ed33f6ac6..9539b724d9 100644 --- a/openapi/components/parameters.yaml +++ b/openapi/components/parameters.yaml @@ -51,7 +51,21 @@ client_include: name: include in: query - description: Include child relationships of the Client Object. + description: | + Include child relationships of the Client Object. ie ?include=documents,system_logs + + ```html + Available includes: + + contacts [All contacts related to the client] + documents [All documents related to the client] + gateway_tokens [All payment tokens related to the client] + activities [All activities related to the client] + ledger [The client ledger] + system_logs [System logs related to the client] + group_settings [The group settings object the client is assigned to] + + ``` required: false schema: type: string @@ -204,7 +218,24 @@ index: name: index in: query - description: 'Replaces the default response index from data to a user specific string' + description: | + Replaces the default response index from data to a user specific string + + ie. + + ```html + ?index=new_index + ``` + + response is wrapped + + ```json + { + 'new_index' : [ + ..... + ] + } + ``` required: false schema: type: string diff --git a/openapi/components/parameters/default_filters.yaml b/openapi/components/parameters/default_filters.yaml index bd35f35ef7..4134c79ab8 100644 --- a/openapi/components/parameters/default_filters.yaml +++ b/openapi/components/parameters/default_filters.yaml @@ -7,6 +7,11 @@ - active - archived - deleted + + ```html + GET /api/v1/invoices?status=archived,deleted + Returns only archived and deleted invoices + ``` required: false schema: type: string @@ -16,6 +21,11 @@ in: query description: | Filters the entity list by client_id. Suitable when you only want the entities of a specific client. + + ```html + GET /api/v1/invoices?client_id=AxB7Hjk9 + Returns only invoices for the specified client + ``` required: false schema: type: string @@ -25,6 +35,11 @@ in: query description: | Filters the entity list by the created at timestamp. Parameter value can be a datetime string or unix timestamp + + ```html + GET /api/v1/invoices?created_at=2022-01-10 + Returns entities created on January 10th, 2022 + ``` required: false schema: type: integer @@ -34,6 +49,11 @@ in: query description: | Filters the entity list by the updated at timestamp. Parameter value can be a datetime string or unix timestamp + + ```html + GET /api/v1/invoices?updated_at=2022-01-10 + Returns entities last updated on January 10th, 2022 + ``` required: false schema: type: integer @@ -43,6 +63,11 @@ in: query description: | Filters the entity list by entities that have been deleted. + + ```html + GET /api/v1/invoices?is_deleted=true + Returns only soft-deleted entities + ``` required: false schema: type: boolean @@ -52,6 +77,11 @@ in: query description: | Filters the entity list by an associated vendor + + ```html + GET /api/v1/purchases?vendor_id=AxB7Hjk9 + Returns only purchases for the specified vendor + ``` required: false schema: type: string @@ -61,8 +91,13 @@ in: query description: | Filters the entity list and only returns entities for clients that have not been deleted + + ```html + GET /api/v1/invoices?filter_deleted_clients=true + Returns only invoices for active (non-deleted) clients + ``` required: false schema: type: string example: ?filter_deleted_clients=true - ########################### Generic filters available across all filter ################################## + ########################### Generic filters available across all filter ################################## \ No newline at end of file diff --git a/openapi/components/schemas/client_request.yaml b/openapi/components/schemas/client_request.yaml index 5b3fd1fdab..51f589125c 100644 --- a/openapi/components/schemas/client_request.yaml +++ b/openapi/components/schemas/client_request.yaml @@ -16,11 +16,11 @@ name: description: 'The name of the client company or organization' type: string - example: "Jim's Housekeeping" + example: "Bob & Co Housekeeping" website: description: 'The website URL of the client company or organization' type: string - example: 'https://www.jims-housekeeping.com' + example: 'https://www.boandco-housekeeping.com' private_notes: description: 'Notes that are only visible to the user who created the client' type: string @@ -58,7 +58,10 @@ type: string example: '555-3434-3434' country_id: - description: "The unique identifier of the client's country" + description: | + The unique identifier of the client's country expressed by the countries ISO number. + + Optionally, instead of the country_id you can pass either the iso_3166_2 or iso_3166_3 country code into the country_code property. type: number format: integer example: '1' @@ -110,7 +113,10 @@ type: string example: '6110' shipping_country_id: - description: "The unique identifier of the country for the client's shipping address" + description: | + The unique identifier of the client's shipping country expressed by the countries ISO number. + + Optionally, instead of the shipping_country_id you can pass either the iso_3166_2 or iso_3166_3 country code into the shipping_country_code property. type: number format: integer example: '4' diff --git a/openapi/misc/misc.yaml b/openapi/misc/misc.yaml index 4052b43db9..3d649e5b21 100644 --- a/openapi/misc/misc.yaml +++ b/openapi/misc/misc.yaml @@ -12,11 +12,31 @@ tags: ```html /api/v1/login?include=company,user ``` + - name: clients x-displayName: Clients - - # description: | - # Endpoint definitions for interacting with clients. + description: | + The Clients API provides endpoints for managing client records within your company. A client represents a customer + or business entity that you provide services or products to. + + ## Key Features + - Create, read, update, and delete client records + - Manage client contact information and billing details + - View client-specific transaction history + - Handle multiple contacts per client + - Track client-specific settings and preferences + + ## Client Statuses + - Active: Client is currently active and can be billed + - Archived: Client is archived and hidden from active lists + - Deleted: Client is marked for deletion but retained in the database + + ## Best Practices + - Always validate client email addresses + - Use unique client numbers for easy reference + - Keep contact information up to date + - Set appropriate client-specific currency and tax settings + - name: products x-displayName: Products description: | @@ -56,7 +76,7 @@ tags: Endpoint definitions for interacting with payments. - name: quotes - x-displayName:: Quotes + x-displayName: Quotes description: | Endpoint definitions for interacting with quotes. @@ -104,9 +124,18 @@ tags: x-displayName: Reports description: | Endpoint definitions for interacting with reports. - + externalDocs: - description: "https://invoiceninja.github.io" - url: "https://invoiceninja.github.io" + description: "Client Libraries" + x-libraries: + - name: PHP SDK + description: Official PHP client library + url: https://github.com/invoiceninja/sdk-php + packageUrl: https://packagist.org/packages/invoiceninja/sdk-php + language: PHP + - name: User Guide + description: Official user guide + url: https://invoiceninja.github.io + security: - ApiKeyAuth: [] diff --git a/openapi/paths.yaml b/openapi/paths.yaml index 1bd847ee86..a9866b30ae 100644 --- a/openapi/paths.yaml +++ b/openapi/paths.yaml @@ -96,7 +96,7 @@ paths: label: curl source: | curl --request POST \ - --url 'https://invoicing.co/api/v1/login?include=company,token' \ + --url 'https://demo.invoiceninja.com/api/v1/login?include=company,token' \ --header 'X-API-TOKEN: YOUR_API_TOKEN_HERE' \ --header 'X-Requested-With: XMLHttpRequest' \ --header 'Accept: application/json' diff --git a/openapi/paths/clients.yaml b/openapi/paths/clients.yaml index 3f262e86df..f14af99668 100644 --- a/openapi/paths/clients.yaml +++ b/openapi/paths/clients.yaml @@ -8,7 +8,12 @@ label: php source: | $ninja = new InvoiceNinja("your_token"); - $invoices = $ninja->clients->all(); + $invoices = $ninja->clients->all([ + 'balance' => 'lt:10', // get all clients with a balance less than 10 + 'per_page' => 10, // return 10 results per page + 'page' => 2, // paginate to page 2 + 'include' => 'documents', // include the documents relationship + ]); - lang: curl label: curl source: | @@ -60,64 +65,146 @@ - $ref: "#/components/parameters/updated_at" - $ref: "#/components/parameters/is_deleted" - $ref: "#/components/parameters/filter_deleted_clients" - - $ref: "#/components/parameters/vendor_id" - name: name in: query - description: Filter by client name + description: | + Filter by client name + + ```html + ?name=bob + ``` required: false schema: type: string example: bob - name: balance in: query - description: Filter by client balance, format uses an operator and value separated by a colon. lt,lte, gt, gte, eq + description: | + Filter by client balance, format uses an operator and value separated by a colon. lt,lte, gt, gte, eq + + ```html + ?balance=lt:10 + ``` + + ie all clients whose balance is less than 10 required: false schema: type: string example: lt:10 - name: between_balance in: query - description: Filter between client balances, format uses two values separated by a colon + description: | + Filter between client balances, format uses two values separated by a colon + + ```html + ?between_balance=10:100 + ``` required: false schema: type: string example: 10:100 - name: email in: query - description: Filter by client email + description: | + Filter by client email + + ```html + ?email=bob@gmail.com + ``` required: false schema: type: string example: bob@gmail.com - name: id_number in: query - description: Filter by client id_number + description: | + Filter by client id_number + + ```html + ?id_number=0001 + ``` required: false schema: type: string example: a1039883 - name: number in: query - description: Filter by client number + description: | + Filter by client number + + ```html + ?number=0002 + ``` required: false schema: type: string example: a1039883 - name: filter in: query - description: Filters clients on columns - name, id_number, contact.first_name contact.last_name, contact.email, custom_value1-4 + description: | + Broad filter which targets multiple client columns: + + ```html + name, + id_number, + contact.first_name + contact.last_name, + contact.email, + contact.phone + custom_value1, + custom_value2, + custom_value3, + custom_value4, + ``` + + ```html + ?filter=Bobby + ``` required: false schema: type: string example: a1039883 - name: sort in: query - description: Returns the list sorted by column in ascending or descending order. + description: | + Returns the list sorted by column in ascending or descending order. + + Ensure you use column | direction, ie. + + ```html + ?sort=id|desc + ``` required: false schema: type: string example: id|desc name|desc balance|asc + - name: group + in: query + description: | + Returns the list of clients assigned to {group_id} + + ```html + ?group=X89sjd8 + ``` + required: false + schema: + type: string + example: X89sjd8 + + - name: client_id + in: query + description: | + Returns the list of clients with {client_id} - proxy call to retrieve a client_id wrapped in an array + + ```html + ?client_id=X89sjd8 + ``` + required: false + schema: + type: string + example: X89sjd8 + responses: 200: description: 'A list of clients' @@ -149,12 +236,58 @@ description: | Adds a client to a company + > 🚨 Important When creating (or updating) a client you must include the child contacts with all mutating requests. Client contacts cannot be modified in isolation. - + x-codeSamples: + - lang: php + label: php + source: | + $ninja = new InvoiceNinja("YOUR-TOKEN"); + + $client = $ninja->clients->create([ + 'name' => 'Client Name', + 'contacts' => [ + [ + 'first_name' => 'John', + 'last_name' => 'Smith', + 'email' => 'john@example.com', + 'phone' => '555-0123' + ] + ], + 'address1' => '123 Main St', + 'city' => 'New York', + 'state' => 'NY', + 'postal_code' => '10001', + 'country_id' => '1' + ]); + - lang: curl + label: curl + source: | + curl -X POST https://demo.invoiceninja.com/api/v1/clients \ + -H "X-API-TOKEN: YOUR-TOKEN" \ + -H "Content-Type: application/json" \ + -H "X-Requested-With: XMLHttpRequest" \ + -d '{ + "name": "Client Name", + "contacts": [ + { + "first_name": "John", + "last_name": "Smith", + "email": "john@example.com", + "phone": "555-0123" + } + ], + "address1": "123 Main St", + "city": "New York", + "state": "NY", + "postal_code": "10001", + "country_id": "1" + }' operationId: storeClient parameters: - $ref: '#/components/parameters/X-API-TOKEN' - $ref: '#/components/parameters/X-Requested-With' + - $ref: '#/components/parameters/index' - $ref: '#/components/parameters/client_include' requestBody: description: Client object that needs to be added to the company @@ -193,10 +326,24 @@ - clients summary: 'Show client' description: 'Displays a client by id' + x-codeSamples: + - lang: php + label: php + source: | + $ninja = new InvoiceNinja("YOUR-TOKEN"); + $client = $ninja->clients->show('clientId123'); + - lang: curl + label: php + source: | + curl -X GET https://demo.invoiceninja.com/api/v1/clients/clientId123 \ + -H "X-API-TOKEN: YOUR-TOKEN" \ + -H "X-Requested-With: XMLHttpRequest" + operationId: showClient parameters: - $ref: '#/components/parameters/X-API-TOKEN' - $ref: '#/components/parameters/X-Requested-With' + - $ref: '#/components/parameters/index' - $ref: '#/components/parameters/client_include' - name: id in: path @@ -234,11 +381,50 @@ tags: - clients summary: 'Update client' - description: 'Handles the updating of a client by id' + description: | + Handles the updating of a client by id + + > 🚨 Important + When creating (or updating) a client you must include the child contacts with all mutating requests. Client contacts cannot be modified in isolation. + + x-codeSamples: + - lang: php + label: php + source: | + $ninja = new InvoiceNinja("YOUR-TOKEN"); + $client = $ninja->clients->update('clientId123', [ + 'name' => 'Updated Name', + 'contacts' => [ + [ + 'first_name' => 'John', + 'last_name' => 'Smith', + 'email' => 'john@example.com' + ] + ] + ]); + - lang: curl + label: curl + source: | + curl -X PUT https://demo.invoiceninja.com/api/v1/clients/clientId123 \ + -H "X-API-TOKEN: YOUR-TOKEN" \ + -H "Content-Type: application/json" \ + -H "X-Requested-With: XMLHttpRequest" \ + -d '{ + "name": "Updated Name", + "contacts": [ + { + "first_name": "John", + "last_name": "Smith", + "email": "john@example.com" + } + ] + }' + operationId: updateClient parameters: - $ref: '#/components/parameters/X-API-TOKEN' - $ref: '#/components/parameters/X-Requested-With' + - $ref: '#/components/parameters/index' - $ref: '#/components/parameters/client_include' - name: id in: path @@ -283,11 +469,32 @@ tags: - clients summary: 'Delete client' - description: 'Handles the deletion of a client by id' + description: | + Handles the deletion of a client by id + + > ❗ Note + Deleting a client does not purge the client from the system. The delete action will remove the clients data from all + views in the application but keep it all on file. A Client can be laterrestored reversing this action. To permanently wipe a client and + all of their records from the system, use the /purge route + + x-codeSamples: + - lang: php + label: php + source: | + $ninja = new InvoiceNinja("YOUR-TOKEN"); + $ninja->clients->delete('clientId123'); + - lang: curl + label: curl + source: | + curl -X DELETE https://demo.invoiceninja.com/api/v1/clients/clientId123 \ + -H "X-API-TOKEN: YOUR-TOKEN" \ + -H "X-Requested-With: XMLHttpRequest" + operationId: deleteClient parameters: - $ref: '#/components/parameters/X-API-TOKEN' - $ref: '#/components/parameters/X-Requested-With' + - $ref: '#/components/parameters/index' - $ref: '#/components/parameters/client_include' - name: id in: path @@ -327,7 +534,8 @@ parameters: - $ref: '#/components/parameters/X-API-TOKEN' - $ref: '#/components/parameters/X-Requested-With' - - $ref: '#/components/parameters/include' + - $ref: '#/components/parameters/index' + - $ref: '#/components/parameters/client_include' - name: id in: path description: 'The Client Hashed ID' @@ -370,6 +578,7 @@ parameters: - $ref: '#/components/parameters/X-API-TOKEN' - $ref: '#/components/parameters/X-Requested-With' + - $ref: '#/components/parameters/index' - $ref: '#/components/parameters/client_include' responses: 200: @@ -436,12 +645,33 @@ - custom_value2 - custom_value3 - custom_value4 - + + x-codeSamples: + - lang: php + label: php + source: | + $ninja = new InvoiceNinja("YOUR-TOKEN"); + $ninja->clients->bulk([ + 'action' => 'archive', + 'ids' => ['clientId1', 'clientId2'] + ]); + - lang: curl + label: curl + source: | + curl -X POST https://demo.invoiceninja.com/api/v1/clients/bulk \ + -H "X-API-TOKEN: YOUR-TOKEN" \ + -H "Content-Type: application/json" \ + -H "X-Requested-With: XMLHttpRequest" \ + -d '{ + "action": "archive", + "ids": ["clientId1", "clientId2"] + }' operationId: bulkClients parameters: - $ref: '#/components/parameters/X-API-TOKEN' - $ref: '#/components/parameters/X-Requested-With' - $ref: '#/components/parameters/index' + - $ref: '#/components/parameters/client_include' requestBody: description: 'Bulk action array' required: true @@ -480,10 +710,26 @@ - clients summary: 'Add client document' description: 'Handles the uploading of a document to a client, please note due to a quirk in REST you will need to use a _method parameter with value of POST' + x-codeSamples: + - lang: php + label: php + source: | + $ninja = new InvoiceNinja("YOUR-TOKEN"); + $ninja->clients->upload('clientId123', '/path/to/document.pdf'); + - lang: curl + label: curl + source: | + curl -X POST https://demo.invoiceninja.com/api/v1/clients/clientId123/upload \ + -H "X-API-TOKEN: YOUR-TOKEN" \ + -H "X-Requested-With: XMLHttpRequest" \ + -F "_method=POST" \ + -F "documents[]=@/path/to/document.pdf" + operationId: uploadClient parameters: - $ref: '#/components/parameters/X-API-TOKEN' - $ref: '#/components/parameters/X-Requested-With' + - $ref: '#/components/parameters/index' - $ref: '#/components/parameters/client_include' - name: id in: path @@ -503,10 +749,24 @@ _method: type: string example: POST - documents: + documents[]: type: array + description: | + Array of files to upload. The files should be sent with the key name 'documents[]'. + + Supported file types: + - PDF (.pdf) + - Word (.doc, .docx) + - Excel (.xls, .xlsx) + - Images (.jpg, .jpeg, .png) + - Text (.txt) + + Maximum file size: 20MB per file items: + type: string format: binary + description: The file contents + example: "@/path/to/document.pdf" responses: 200: description: 'Returns the client object' @@ -539,15 +799,28 @@ description: | Handles purging a client. - Please note this is a destructive action. - + > ❗ Note + This is a destructive action. This action will remove all data associated with the client and cannot be undone. + x-codeSamples: + - lang: php + label: php + source: | + $ninja = new InvoiceNinja("YOUR-TOKEN"); + $ninja->clients->purge('clientId123'); + - lang: curl + label: curl + source: | + curl -X POST https://demo.invoiceninja.com/api/v1/clients/clientId123/purge \ + -H "X-API-TOKEN: YOUR-TOKEN" \ + -H "X-Requested-With: XMLHttpRequest" \ + -H "X-API-PASSWORD: YOUR-PASSWORD" + operationId: purgeClient parameters: - $ref: '#/components/parameters/X-API-TOKEN' - $ref: '#/components/parameters/X-Requested-With' - $ref: '#/components/parameters/X-API-PASSWORD' - - $ref: '#/components/parameters/client_include' - name: id in: path description: 'The Client Hashed ID' @@ -587,12 +860,30 @@ The id parameter is the client that will be the primary client after the merge has completed. The mergeable_client_hashed_id is the client that will be merged into the primary client, this clients records will be updated and associated with the primary client. + + > 🚨 **Important** + This action requires elevated permissions, please note the X-API-PASSWORD header requirements for this route. + + x-codeSamples: + - lang: php + label: php + source: | + $ninja = new InvoiceNinja("YOUR-TOKEN"); + $ninja->clients->merge('primaryClientId', 'mergeableClientId'); + - lang: curl + label: curl + source: | + curl -X POST https://demo.invoiceninja.com/api/v1/clients/primaryClientId/mergeableClientId/merge \ + -H "X-API-TOKEN: YOUR-TOKEN" \ + -H "X-Requested-With: XMLHttpRequest" + operationId: mergeClient parameters: - $ref: '#/components/parameters/X-API-TOKEN' - $ref: '#/components/parameters/X-Requested-With' - - $ref: '#/components/parameters/client_include' - $ref: '#/components/parameters/X-API-PASSWORD' + - $ref: '#/components/parameters/index' + - $ref: '#/components/parameters/client_include' - name: id in: path description: 'The Client Hashed ID' @@ -636,10 +927,37 @@ summary: 'Client statement PDF' description: 'Return a PDF of the client statement' operationId: clientStatement + x-codeSamples: + - lang: php + label: php + source: | + $ninja = new InvoiceNinja("YOUR-TOKEN"); + $statement = $ninja->clients->statement([ + 'client_id' => 'clientId123', + 'start_date' => '2024-01-01', + 'end_date' => '2024-12-31', + 'show_payments_table' => true, + 'show_aging_table' => true + ]); + - lang: curl + label: curl + source: | + curl -X POST https://demo.invoiceninja.com/api/v1/client_statement \ + -H "X-API-TOKEN: YOUR-TOKEN" \ + -H "Content-Type: application/json" \ + -H "X-Requested-With: XMLHttpRequest" \ + -d '{ + "client_id": "clientId123", + "start_date": "2024-01-01", + "end_date": "2024-12-31", + "show_payments_table": true, + "show_aging_table": true + }' parameters: - $ref: '#/components/parameters/X-API-TOKEN' - $ref: '#/components/parameters/X-Requested-With' - - $ref: '#/components/parameters/include' + - $ref: '#/components/parameters/index' + - $ref: '#/components/parameters/client_include' requestBody: description: 'Statement Options' required: true @@ -702,7 +1020,8 @@ parameters: - $ref: '#/components/parameters/X-API-TOKEN' - $ref: '#/components/parameters/X-Requested-With' - - $ref: '#/components/parameters/include' + - $ref: '#/components/parameters/index' + - $ref: '#/components/parameters/client_include' - name: bounce_id in: path description: 'The postmark Bounce ID reference' @@ -745,7 +1064,8 @@ parameters: - $ref: '#/components/parameters/X-API-TOKEN' - $ref: '#/components/parameters/X-Requested-With' - - $ref: '#/components/parameters/include' + - $ref: '#/components/parameters/index' + - $ref: '#/components/parameters/client_include' - name: client in: path description: 'The Client Hashed ID reference'