# ./docs/api/instalacion.md --- title: Installation of Totalum SDK sidebar_position: 1 --- # Introduction The package name is `totalum-api-sdk`. Use the Totalum API SDK to query, filter, modify, create, and delete Totalum data without limits. You can also use the API SDK to generate PDFs, perform OCR on images or PDFs, access ChatGPT, and more. # Ways to Use the API SDK ## Using the totalumSdk for JavaScript This is the easiest way to use the API, as it is an npm package with TypeScript that provides autocomplete for methods and offers a simpler interface for interacting with the API. ## Using the API Directly If you do not want or cannot use the SDK, you can use the Totalum REST API directly. ACCESS THE TOTALUM API DOCUMENTATION --- # Installation Totalum SDK is an npm package, compatible with nodejs and browsers. https://www.npmjs.com/package/totalum-api-sdk ```bash npm i totalum-api-sdk ``` If you are using Totalum from a custom HTML and cannot import it with npm, use the following script: ```html ``` Warning: We only recommend using TotalumSdk from the frontend in a custom HTML page within Totalum, or from a Totalum plugin or event. In all other cases, we recommend using the SDK from your own backend. If you use TotalumSdk from your own frontend that is open to the public, anyone could see your authentication token or apiKey, and could use it intentionally. --- # Authentication **Note:** If you use totalumSdk inside a totalum plugin, you don't need to authenticate, you can start using totalum like this: `modules.totalumSdk.your.function();` -> example: `modules.totalumSdk.crud.query('your_table')` You can choose to use one of the two authentication methods offered by Totalum Sdk: - **Token**: You can use an access token to authenticate. This token can be obtained from the localStorage of your browser from the web https://web.totalum.app - **ApiKey**: (RECOMMENDED OPTION) You can use an ApiKey to authenticate. This ApiKey can be obtained in the **Api Keys** section of the **Configuration** section of Totalum. ## ES Module Import: ```typescript import {AuthOptions, TotalumApiSdk} from 'totalum-api-sdk'; // CHOICE FROM USE accessToken OR apiKey (API KEY IS RECOMMENDED) // the auth using token const options: AuthOptions = { token:{ accessToken: 'YOUR TOKEN' // get it from totalum project web localStorage } } // the auth using api key const options: AuthOptions = { apiKey:{ 'api-key': 'your_api_key', //the api key secret that is shown only once, example: sk_23r23r23r... } } const totalumClient = new TotalumApiSdk(options); // execute some TotalumApiSdk function const result = await totalumClient.crud.query('your_table_name'); ``` ## CommonJS Require: ```javascript const totalum = require('totalum-api-sdk'); // CHOICE FROM USE accessToken OR apiKey (API KEY IS RECOMMENDED) // the auth using token const options = { token:{ accessToken: 'YOUR TOKEN' // get it from totalum project web localStorage } } // the auth using api key const options = { apiKey:{ 'api-key': 'your_api_key', //the api key secret that is shown only once, example: sk_23r23r23r... } } const totalumClient = new totalum.TotalumApiSdk(options); // execute some TotalumApiSdk function const result = await totalumClient.crud.query('your_table_name'); ``` ## HTML script import: Use this way if you are using standalone html, and you cannot import npm packages ```html ``` --- # ./docs/api/uso-de-la-api.md --- id: api title: Open API Documentation sidebar_position: 2 --- #### Warning: If your environment is JavaScript or Node.js, we recommend using the TotalumSdk npm package to simplify working with the Sdk API. Access to the Totalum HTTP REST API Documentation --- # ./docs/api/crearDatos.md --- title: Create Data sidebar_position: 5 --- # Create Data --- **📚 Setup Required:** For installation and usage of the Totalum SDK or API, see the [Installation Guide](/docs/api/instalacion). --- ### create item **Use Case:** Create an for from your element table. ```javascript // create item from your_element_table_name, you need to pass at least the required properties const tableElementName = 'your_element_table_name'; // replace 'your_element_table_name' with the name of your element table const result = await totalumClient.crud.createRecord(tableElementName, {your_item_property: 'new value'}); ``` **Example:** Imagine you have a table called `client` with the following properties: - `name` (text) - `email` (text) - `phone` (text) - `birthday` (date) And you want to create a new client with name `John Doe`, the email `jhon@gmail.com`, the phone `+34 123 456 789`, and the birthday `1990-01-01`. ```javascript const tableElementName = 'client'; const clientToCreate = { name: 'John Doe', email: 'jhon@gmail.com', phone: '+34 123 456 789', birthday: new Date('1990-01-01') }; const result = await totalumClient.crud.createRecord(tableElementName, clientToCreate); // The response contains the full created record const createdClient = result.data; const insertedId = createdClient._id; // this is the id of the client you just created console.log('Created client:', createdClient); ``` Note: If you want to create a field that is a type options, and select multiple options is enabled, you must put the options separated by commas, like this: ```javascript const result = await totalumClient.crud.createRecord('client', {optionsField: 'option1, option2, option3'}); ``` ### create item and add reference to another item (One to Many reference) **Use Case:** THIS IS ONLY FOR ONE TO MANY OR MANY TO ONE REFERENCES, IF YOU WANT TO CREATE A MANY TO MANY REFERENCE, SEE THE NEXT SECTION. Imagine you have a table called `client` and other called `order` that are referenced in a one to many relationship, (one client can have many orders). `client` table properties: - `name` (text) - `email` (text) - `phone` (text) - `birthday` (date) `order` table properties: - `summary` (text) - `date` (date) - `import` (number) - `client` (reference to client table) As is a one to many relationship, this tables are linked by a reference in the `order` table. So you see a property called `client` in the `order` table that is a reference to the `client` table. So, If you want to create a new `order` and link it to a `client` you can do it like this: ```javascript let clientIdToAddInOrder = '5f9b2b1b9c6f6b0001a3b2b1'; const orderToCreate = { summary: 'my order summary', date: new Date(), import: 1000, client: clientIdToAddInOrder // this is the reference to the client }; const result = await totalumClient.crud.createRecord('order', orderToCreate); // The response contains the full created record const createdOrder = result.data; const insertedId = createdOrder._id; // this is the id of the order you just created ``` ### create item and add reference to another item (Many to Many reference) **Use Case:** THIS IS ONLY FOR MANY TO MANY REFERENCES, IF YOU WANT TO CREATE A ONE TO MANY OR MANY TO ONE REFERENCE, SEE THE PREVIOUS SECTION. Imagine you have a table called `client` and other called `product` that are referenced in a many to many relationship, (one client can have many orders, and one order can have many clients). `client` table properties: - `name` (text) - `email` (text) - `phone` (text) - `birthday` (date) `product` table properties: - `summary` (text) - `date` (date) - `import` (number) As is a many to many relationship, this tables are linked by a a third join table. So you don't see id reference in the `client` or `product` tables. So if you want to create a new `client` and link it to a `product` you can do it like this: ```javascript const productToCreate = { summary: 'my product summary', date: new Date(), import: 1000 }; const result = await totalumClient.crud.createRecord('product', productToCreate); // The response contains the full created record const createdProduct = result.data; const productId = createdProduct._id; // this is the id of the product you just created const clientIdToAddInProduct = '5f9b2b1b9c6f6b0001a3b2b1'; // this is just an example const propertyName = 'client'; // this is the name of the property in the product table that is a reference to the client table const result2 = await totalumClient.crud.addManyToManyReferenceRecord('product', productId, propertyName, clientIdToAddInProduct); ``` If you want to see more many to many relation examples, see the edit data section. --- # ./docs/api/editarDatos.md --- title: Edit Data sidebar_position: 4 --- # Edit Data --- **📚 Setup Required:** For installation and usage of the Totalum SDK or API, see the [Installation Guide](/docs/api/instalacion). --- ### edit item by id **Use Case:** Edit an item by id from your element table. ```javascript // edit item by id from your_element_table_name, you can edit 1 or multiple properties at the same time (like a patch) const tableElementName = 'your_element_table_name'; // replace 'your_element_table_name' with the name of your element table let your_item_id = 'your_item_id'; // replace 'your_item_id' with the id of the item object const result = await totalumClient.crud.editRecordById(tableElementName, your_item_id, {your_item_property: 'new value'}); ``` **Example:** Imagine you have a table called `client` with the following properties: - `name` (text) - `email` (text) - `phone` (text) - `birthday` (date) And you want to edit the client with id `5f9b2b1b9c6f6b0001a3b2b1` and change the name to `John Doe`, the phone to `+34 123 456 789`, and the birthday to `1990-01-01`. ```javascript const tableElementName = 'client'; let your_item_id = '5f9b2b1b9c6f6b0001a3b2b1'; const result = await totalumClient.crud.editRecordById(tableElementName, your_item_id, {name: 'John Doe', phone: '+34 123 456 789', birthday: new Date('1990-01-01')}); // The response contains the full updated record const updatedClient = result.data; console.log('Updated client:', updatedClient); ``` Note: If you want to edit a field that is a type options, and select multiple options is enabled, you must put the options separated by commas, like this: ```javascript const result = await totalumClient.crud.editRecordById('client', your_item_id, {optionsField: 'option1, option2, option3'}); ``` ### Add or edit an item reference to another item (add or edit reference) (One to Many reference) **Use Case:** THIS IS ONLY FOR ONE TO MANY OR MANY TO ONE REFERENCES, IF YOU WANT TO ADD OR EDIT A MANY TO MANY REFERENCE, SEE THE NEXT SECTION. Imagine you have a table called `client` and other called `order` that are referenced in a one to many relationship, (one client can have many orders). `client` table properties: - `name` (text) - `email` (text) - `phone` (text) - `birthday` (date) `order` table properties: - `summary` (text) - `date` (date) - `import` (number) - `client` (reference to client table) As is a one to many relationship, this tables are linked by a reference in the `order` table. So you see a property called `client` in the `order` table that is a reference to the `client` table. So, If you want to create a new `order` and link it to a `client` you can do it like this: ```javascript let clientIdToAddInOrder = '5f9b2b1b9c6f6b0001a3b2b1'; const orderToCreate = { summary: 'my order summary', date: new Date(), import: 1000, client: clientIdToAddInOrder // this is the reference to the client }; const result = await totalumClient.crud.createRecord('order', orderToCreate); ``` If you want to take an existing `order` and link it to a `client` you can do it like this: ```javascript let clientIdToAddInOrder = '5f9b2b1b9c6f6b0001a3b2b1'; let orderId = '5f9b2b1b9c6f6b0001a3b2b1'; const result = await totalumClient.crud.editRecordById('order', orderId, {client: clientIdToAddInOrder}); ``` If you want to remove the reference to a `client` from an `order` you can do it like this: ```javascript let orderId = '5f9b2b1b9c6f6b0001a3b2b1'; const result = await totalumClient.crud.editRecordById('order', orderId, {client: null}); // now this order has no client linked ``` ### Add or edit an item to another item (add or edit reference) (Many to Many reference) **Use Case:** THIS IS ONLY FOR MANY TO MANY REFERENCES, IF YOU WANT TO ADD OR EDIT A ONE TO MANY OR MANY TO ONE REFERENCE, SEE THE PREVIOUS SECTION. Imagine you have a table called `client` and other called `product` that are referenced in a many to many relationship, (one client can have many products, and one product can have many clients). `client` table properties: - `name` (text) - `email` (text) - `phone` (text) - `birthday` (date) `product` table properties: - `name` (text) - `price` (number) - `category` (options) As is a many to many relationship, this tables are linked by a a third join table. So you don't see id reference in the `client` or `product` tables. So, if you want to create a new `product` and link it to a `client` you can do it like this: ```javascript const productToCreate = { name: 'my product name', price: 1000, category: 'my category' }; const result = await totalumClient.crud.createRecord('product', productToCreate); // The response contains the full created record const createdProduct = result.data; const productId = createdProduct._id; const clientId = '5f9b2b1b9c6f6b0001a3b2b1'; const propertyName = 'products'; // this is the name of the property in the client table that references the product table const result = await totalumClient.crud.addManyToManyReferenceRecord('client', clientId, propertyName, productId); ``` If you want to take an existing `product` and link it to a `client` you can do it like this: ```javascript const clientId = '5f9b2b1b9c6f6b0001a3b2b1'; const productId = '5f9b2b1b9c6f6b0001a3b2b1'; const propertyName = 'products'; // this is the name of the property in the client table that references the product table const result = await totalumClient.crud.addManyToManyReferenceRecord('client', clientId, propertyName, productId); ``` If you want to remove the reference to a `product` from a `client` you can do it like this: ```javascript const clientId = '5f9b2b1b9c6f6b0001a3b2b1'; const productId = '5f9b2b1b9c6f6b0001a3b2b1'; const propertyName = 'products'; // this is the name of the property in the client table that references the product table const result = await totalumClient.crud.dropManyToManyReferenceRecord('client', clientId, propertyName, productId); ``` --- # ./docs/api/borrarDatos.md --- title: Delete Data sidebar_position: 6 --- # Delete Data --- **📚 Setup Required:** For installation and usage of the Totalum SDK or API, see the [Installation Guide](/docs/api/instalacion). --- # delete item by id **Use Case:** Delete an item by id from your element table. ```javascript // delete item by id from your_element_table_name const tableElementName = 'your_element_table_name'; // replace 'your_element_table_name' with the name of your element table let your_item_id = 'your_item_id'; // replace 'your_item_id' with the id of the item object const result = await totalumClient.crud.deleteRecordById(tableElementName, your_item_id); ``` **Example:** Imagine you have a table called `client` with multiple client items, and you want to delete the client with id `5f9b2b1b9c6f6b0001a3b2b1`. ```javascript let itemIdToDelete = '5f9b2b1b9c6f6b0001a3b2b1'; const result = await totalumClient.crud.deleteRecordById('client', itemIdToDelete); ``` # delete item reference to another item (One to Many reference) **Use Case:** THIS IS ONLY FOR ONE TO MANY OR MANY TO ONE REFERENCES, IF YOU WANT TO DELETE A MANY TO MANY REFERENCE, SEE THE NEXT SECTION. Imagine you have a table called `client` and other called `order` that are referenced in a one to many relationship, (one client can have many orders). You want to delete the reference of the client to the order with id `5f9b2b1b9c6f6b0001a3b2b2`. That means that you only want to delete the reference, the client and the order will not be deleted. ```javascript const tableElementName = 'order' let orderItemId = '5f9b2b1b9c6f6b0001a3b2b2'; const result = await totalumClient.crud.editRecordById(tableElementName, orderItemId, {client: null}); ``` # delete item reference to another item (Many to Many reference) **Use Case:** THIS IS ONLY FOR MANY TO MANY REFERENCES, IF YOU WANT TO DELETE A ONE TO MANY OR MANY TO ONE REFERENCE, SEE THE PREVIOUS SECTION. Imagine you have a table called `client` and other called `product` that are referenced in a many to many relationship, (one client can have many products, and one product can have many clients). You want to delete the reference of the client to the product with id `5f9b2b1b9c6f6b0001a3b2b2`. That means that you only want to delete the reference, the client and the product will not be deleted. ```javascript const tableElementName = 'client' let clientItemId = '5f9b2b1b9c6f6b0001a3b2b2'; const propertyName = 'products'; // this is the name of the property in the client table that is a reference to the product table const productId = '5f9b2b1b9c6f6b0001a3b2b2'; const result = await totalumClient.crud.dropManyToManyReferenceRecord(tableElementName, clientItemId, propertyName, productId); ``` --- # ./docs/api/filtrarDatos.md --- title: Read and Filter Data sidebar_position: 3 --- # Read and Filter Data --- **📚 Setup Required:** For installation and usage of the Totalum SDK or API, see the [Installation Guide](/docs/api/instalacion). --- ## Get item by id **Use Case:** Get only one item by id from your element table ```javascript // get item by id from your_element_table_name const tableElementName = 'your_element_table_name'; // replace 'your_element_table_name' with the name of your element table let your_item_id = 'your_item_id'; // replace 'your_item_id' with the id of the item object const result = await totalumClient.crud.getRecordById(tableElementName, your_item_id); const item = result.data; ``` **example:** Imagine you have a table named `client`, and this table has some items inside. You want to get a client by id, so you can do this: ```javascript const tableElementName = 'client'; let clientId = 'the_client_id'; // replace 'the_client_id' with the id of the item object const result = await totalumClient.crud.getRecordById(tableElementName, clientId); const client = result.data; ``` --- ## Query (Recommended) `totalumClient.crud.query()` is the **recommended** method for reading data. > **Note:** If you get an error like `query is not a function`, update the SDK: `npm install totalum-api-sdk@latest` > If you are using deprecated methods like `getRecords`, `getNestedData`, `getManyToManyReferencesRecords`, or `nestedFilter`, see the [Deprecated Get Methods](./deprecated-get-methods) page for migration guide. It supports: - **Nested relations** (oneToMany, manyToOne, manyToMany) at any depth - **Filtering** with exact match, comparison operators, regex, `_or`, `in`, `contains`, `startsWith`, `endsWith` - **Sorting**, **pagination** (`_limit`, `_offset`) - **Parent filtering by children** (`_has`) - **Child counts** (`_count`) - **Field selection** (`_select`, `_omit`) - **Aggregations** (`_aggregate`, `_groupBy`) --- ### Get items (simple) Get items from a table without any filters (default limit: 50 items). ```javascript const result = await totalumClient.crud.query('client'); const clients = result.data; ``` ### Get items with nested relations **Use Case:** Imagine you have 3 tables: `client`, `order` and `product`. You want to get clients with all their orders and each order's products. ```javascript const result = await totalumClient.crud.query('client', { order: { product: true } }); const clients = result.data; /* Result structure: [ { _id: 'client_id_1', name: 'Client 1', order: [ { _id: 'order_id_1', date: '2023-01-01', product: [ { _id: 'product_id_1', name: 'Product 1' }, { _id: 'product_id_2', name: 'Product 2' } ] }, ] }, // more clients... ] */ ``` **Important:** The property names in the query (`order`, `product`) must be the **property names** (field names) defined in your table, not the table names. You can use `true` as a shorthand for `{}` — both expand the relation with default settings. ### Get items with manyToOne relations **Use Case:** Imagine you have a `task` table with a `employee` field (manyToOne) and `employee` has a `company` field (manyToOne). You want to get tasks with the full employee and company data. ```javascript const result = await totalumClient.crud.query('task', { employee: { company: true } }); const tasks = result.data; /* Result structure (manyToOne returns a single object, not an array): [ { _id: 'task_id_1', title: 'Fix bug', employee: { _id: 'emp_id_1', name: 'Alice', company: { _id: 'company_id_1', name: 'Acme Corp' } } }, // more tasks... ] */ ``` ### Get items with manyToMany relations **Use Case:** Imagine `employee` has a manyToMany relation `project`. You want to get all employees with their projects. ```javascript const result = await totalumClient.crud.query('employee', { project: true }); const employees = result.data; /* [ { _id: 'emp_id_1', name: 'Alice', project: [ { _id: 'proj_id_1', name: 'Website Redesign' }, { _id: 'proj_id_2', name: 'Mobile App' } ] }, // more employees... ] */ ``` --- ### Filter items (exact match) ```javascript const result = await totalumClient.crud.query('client', { _filter: { name: 'John' } }); const clients = result.data; ``` ### Filter with comparison operators Supported operators: `gte` (>=), `lte` (<=), `ne` (!=), `in`, `nin`, `contains`, `startsWith`, `endsWith`, `regex`. ```javascript // Get clients older than 18 with birthday after 2000 const result = await totalumClient.crud.query('client', { _filter: { age: { gte: 18 }, birthday: { gte: new Date('2000-01-01') } } }); ``` ### Filter with OR conditions ```javascript // Get clients named 'John' OR aged 18+ const result = await totalumClient.crud.query('client', { _filter: { _or: [ { name: 'John' }, { age: { gte: 18 } } ] } }); ``` ### Filter with AND + OR combined ```javascript // Get clients (named 'John' OR aged 18+) AND address contains 'street' const result = await totalumClient.crud.query('client', { _filter: { _or: [ { name: 'John' }, { age: { gte: 18 } } ], address: { contains: 'street' } } }); ``` ### Filter with `in` operator ```javascript // Get clients with status 'active' or 'pending' const result = await totalumClient.crud.query('client', { _filter: { status: { in: ['active', 'pending'] } } }); ``` ### Filter with `regex` ```javascript // Get clients whose name contains 'john' (case insensitive) const result = await totalumClient.crud.query('client', { _filter: { name: { regex: 'john', options: 'i' } } }); ``` ### Filter with `contains`, `startsWith`, `endsWith` ```javascript // These are shortcuts for common regex patterns const result = await totalumClient.crud.query('client', { _filter: { name: { startsWith: 'Jo' }, // names starting with "Jo" email: { endsWith: '@gmail.com' }, // gmail emails address: { contains: 'street' } // address contains "street" } }); ``` --- ### Sort results ```javascript // Sort by name ascending const result = await totalumClient.crud.query('client', { _sort: { name: 'asc' } }); // Sort by age descending const result2 = await totalumClient.crud.query('client', { _sort: { age: 'desc' } }); // You can also use 1 (asc) and -1 (desc) const result3 = await totalumClient.crud.query('client', { _sort: { name: 1, age: -1 } }); ``` ### Pagination (limit and offset) ```javascript // Get first 10 clients const result = await totalumClient.crud.query('client', { _limit: 10 }); // Get clients 11-20 (skip first 10) const result2 = await totalumClient.crud.query('client', { _limit: 10, _offset: 10 }); ``` ### Limit children ```javascript // Get companies with only the first 5 employees const result = await totalumClient.crud.query('company', { employee: { _limit: 5, _sort: { name: 'asc' } } }); ``` --- ### Filter on children You can filter children and also use `_has` to filter parents based on their children. ```javascript // Get companies that have at least one active employee const result = await totalumClient.crud.query('company', { employee: { _filter: { status: 'active' }, _has: true // only return companies that have matching employees } }); ``` `_has` supports: `true` (same as `'some'`), `'some'`, `'none'`, `'every'`. ```javascript // Get companies with NO employees const result = await totalumClient.crud.query('company', { employee: { _has: 'none' } }); ``` ### Count children ```javascript // Get companies with the count of their employees const result = await totalumClient.crud.query('company', { employee: { _count: true } }); const companies = result.data; /* [ { _id: 'company_id_1', name: 'Acme Corp', employee: [ ... ], _count: { employee: 15 } } ] */ ``` ### Count total (root level) ```javascript // Get total count of matching records (useful for pagination) const result = await totalumClient.crud.query('client', { _filter: { status: 'active' }, _count: true, _limit: 10 }); const clients = result.data; // Each record will have: _count: { _total: 150 } // So you know there are 150 total active clients, but only 10 returned ``` --- ### Select specific fields ```javascript // Only return name and email fields const result = await totalumClient.crud.query('client', { _select: { name: true, email: true } }); // Result: [{ _id: '...', name: 'John', email: 'john@...' }] // Other fields like age, address, etc. are NOT returned ``` ### Omit specific fields ```javascript // Return all fields EXCEPT password and internal_notes const result = await totalumClient.crud.query('client', { _omit: { password: true, internal_notes: true } }); ``` **Note:** `_select` and `_omit` cannot be used together at the same level. --- ### Hide children from response (_include: false) Use `_include: false` when you want to use `_has` or `_count` on children but don't want the actual child records in the response. ```javascript // Get companies that have employees, with employee count, but don't include employee data const result = await totalumClient.crud.query('company', { employee: { _has: true, _count: true, _include: false // don't include employee array in response } }); // Result: [{ _id: '...', name: 'Acme', _count: { employee: 15 } }] // No 'employee' array in the response ``` --- ### Aggregations Aggregate data with `_sum`, `_avg`, `_min`, `_max`, `_count`. ```javascript // Get total and average amount of all invoices const result = await totalumClient.crud.query('invoice', { _aggregate: { _sum: { amount: true }, _avg: { amount: true }, _count: true } }); /* Result: [ { _aggregate: { _sum: { amount: 50000 }, _avg: { amount: 250 }, _count: 200 } } ] */ ``` ### Aggregations with groupBy ```javascript // Get total invoice amount grouped by status const result = await totalumClient.crud.query('invoice', { _filter: { date: { gte: new Date('2024-01-01') } }, _aggregate: { _sum: { amount: true }, _count: true }, _groupBy: 'status' }); /* Result: [ { _group: { status: 'paid' }, _aggregate: { _sum: { amount: 35000 }, _count: 150 } }, { _group: { status: 'pending' }, _aggregate: { _sum: { amount: 15000 }, _count: 50 } } ] */ ``` ### Child aggregations ```javascript // Get companies with total salary of their employees const result = await totalumClient.crud.query('company', { employee: { _aggregate: { _sum: { salary: true }, _avg: { salary: true } }, _include: false } }); /* Result: [ { _id: 'company_id_1', name: 'Acme Corp', _aggregate: { employee: { _sum: { salary: 500000 }, _avg: { salary: 50000 } } } } ] */ ``` --- ### Full example: combining multiple features ```javascript // Get companies in Spain with active employees, count tasks per employee, sort by name const result = await totalumClient.crud.query('company', { _filter: { country: 'Spain' }, _sort: { name: 'asc' }, _limit: 10, _count: true, employee: { _filter: { status: { in: ['active', 'probation'] } }, _has: true, _count: true, _sort: { name: 'asc' }, _limit: 20, task: { _sort: { createdAt: 'desc' }, _limit: 5 } } }); ``` --- ## Get the historic updates of a record by its ID. **Use Case:** You can get all changes that have been made to a record. ```javascript const result = await totalumClient.crud.getHistoricRecordUpdatesById(yourRecordId); // replace yourRecordId with the id of the record const updates = result.data; ``` --- ## Filter using your custom mongoDb aggregation query **Use Case:** If you need to do a super complex custom query that is not supported by the previous methods, you can use this method to do a custom mongoDb aggregation query. This method is very powerful, you can do any query you want, but you need to know how to write mongoDb aggregation queries. See the documentation of mongoDb aggregation queries here: https://docs.mongodb.com/manual/aggregation/. Aggregation queries are very powerful for do custom complex queries like joins, group by, union, etc. (the same power as sql queries) **Note:** In Totalum mongoDb Database the tables and items has the following structure: ```json "_id": 2342342342342, // here goes all the properties of the item with the custom names and values that you have defined "property_name": "value", "property_name2": "value2", "property_name2": "value2" //etc... "createdAt": "2021-01-01T00:00:00.000Z", "updatedAt": "2021-01-01T00:00:00.000Z" ``` #### Each table in Totalum is a mongoDb collection (adding data_ prefix), and each record in the table is a document in the collection. #### So for example, if you have a table named `product`, in the mongoDb database the collection will be named `data_product`. #### Important Information: - **For match by Id (ObjectId)**, as the mongoDb query is a string, you need to put: ObjectId('your_id') in the query string, instead of just 'your_id'. - **For match by date**, you need to put the date in the format: Date('your_date') in the query string, instead of just 'your_date'. Ideally provide a iso date string like '2021-01-01T00:00:00.000Z' for avoid time zone issues. ```javascript // filter results from your_element_table_name applying a filter query (a custom mongodb aggregation query) const customMongoDbAggregationQueryInString = ` your custom mongo aggregation query in string, for more info: https://docs.mongodb.com/manual/aggregation/ or ask to chatgpt, he is very good writing mongo aggregation queries ;) `; const result = await totalumClient.filter.runCustomMongoAggregationQuery(tableElementName, customMongoDbAggregationQueryInString); ``` **example** Imagine you have a table named `product`, with properties `name` (text), `price` (number), `provider` (many to one relation with relationship with the table `provider`). And you want to get all the products that have a price greater than 10, and that have a provider that have the name 'John', and also return all products with the full provider autofill, so you can do this: ```javascript const tableElementName = 'product'; const customMongoDbAggregationQueryInString = ` [ { $match: { "price": {$gte: 10} } }, // Join the data_product with data_provider using provider as the linking _id { $lookup: { from: "data_provider", // we add the prefix "data_" to the table name localField: "provider", foreignField: "_id", as: "provider" // Now storing the result directly in the "provider" field } }, { $match: { "provider.name": "John" } }, // Simplify the provider to be an object instead of an array { $addFields: { "provider": { $arrayElemAt: ["$provider", 0] } } } ] `; const result = await totalumClient.filter.runCustomMongoAggregationQuery(tableElementName, customMongoDbAggregationQueryInString); const items = result.data; ``` --- --- ## Deprecated Methods The following methods are deprecated. See the full documentation and migration guide in the [Deprecated Get Methods](./deprecated-get-methods) page. --- # ./docs/api/howFilterWorks.md --- title: How filter works sidebar_position: 4 --- # How Filter Works This page describes the filter format used with `totalumClient.crud.query()`. > If you are using deprecated methods like `getRecords`, `getNestedData`, `getManyToManyReferencesRecords`, or `nestedFilter`, see [How Filter Works (Deprecated)](./deprecated-how-filter-works) for the old filter format. --- ## Basic structure ```javascript const result = await totalumClient.crud.query('your_table', { _filter: { property_name: "value" }, _sort: { property_name: "asc" }, // "asc" or "desc" _limit: 50, _offset: 0, }); ``` --- ## How pagination works Use `_limit` to set the number of items per page and `_offset` to skip items. Default limit is 100. ```javascript // Page 1: items 0-49 { _limit: 50, _offset: 0 } // Page 2: items 50-99 { _limit: 50, _offset: 50 } ``` ## How sorting works Use `_sort` with `"asc"` (ascending) or `"desc"` (descending): ```javascript { _sort: { name: "asc" } } { _sort: { created_at: "desc" } } ``` --- ## Filter operators ### Filter by exact value (string, number, or date) ```javascript { _filter: { name: "John" } } { _filter: { age: 25 } } { _filter: { date: "2024-01-01T00:00:00.000Z" } } ``` ### Filter by partial string (regex) ```javascript { _filter: { name: { regex: "john", options: "i" } } } // options: "i" = case insensitive ``` ### Filter by number range ```javascript { _filter: { price: { gte: 1, lte: 10 } } } ``` ### Filter by date range ```javascript { _filter: { date: { gte: "2024-01-01T00:00:00.000Z", lte: "2024-01-10T00:00:00.000Z" } } } ``` ### Filter by not equal to ```javascript { _filter: { status: { ne: "inactive" } } } ``` ### Filter by list (in / not in) ```javascript { _filter: { status: { in: ["active", "pending"] } } } { _filter: { status: { nin: ["deleted"] } } } ``` ### Filter by contains, startsWith, endsWith ```javascript { _filter: { name: { contains: "john" } } } { _filter: { name: { startsWith: "jo" } } } { _filter: { email: { endsWith: "@gmail.com" } } } ``` ### Filter by a table relation (One to Many) **Use Case:** Imagine you have 2 tables, `client` and `order`. Each client can have multiple orders. You want to get all the orders of a specific client. ```javascript const result = await totalumClient.crud.query('order', { _filter: { client: "the_client_id" } }); ``` --- ## Combining filters ### AND condition (all must match) All properties at the top level of `_filter` are combined with AND: ```javascript { _filter: { status: "active", country: "Spain", age: { gte: 18 }, name: { regex: "john", options: "i" }, role: { ne: "admin" } } } ``` ### OR condition (at least one must match) Use `_or` to combine conditions with OR: ```javascript { _filter: { _or: [ { status: "active" }, { status: "pending" }, { age: { gte: 65 } } ] } } ``` ### AND + OR combined ```javascript { _filter: { country: "Spain", // AND this _or: [ { status: "active" }, // OR this { status: "pending" } // OR this ] } } ``` This filter will return the items where country is "Spain" AND status is "active" or "pending". --- ## Full example ```javascript const result = await totalumClient.crud.query('product', { _filter: { category: "electronics", price: { gte: 10, lte: 500 }, name: { regex: "phone", options: "i" }, }, _sort: { price: "asc" }, _limit: 20, _offset: 0, }); const items = result.data; ``` --- # ./docs/api/enviar-emails.md --- title: Send Emails sidebar_position: 2 --- # Send Emails Totalum allows you to send emails programmatically using the Totalum API or SDK. The email service supports custom HTML content, attachments, CC, BCC, and reply-to options. --- **📚 Setup Required:** For installation and usage of the Totalum SDK or API, see the [Installation Guide](/docs/api/instalacion). --- ## Send a basic email ```javascript const emailPayload = { to: ['recipient@example.com'], subject: 'Your email subject', html: '

Hello

This is the email content in HTML

', }; const result = await totalumClient.email.sendEmail(emailPayload); ``` ## Send an email with all options ```javascript const emailPayload = { to: ['recipient1@example.com', 'recipient2@example.com'], // array of recipients subject: 'Your email subject', html: '

Hello

This is the email content in HTML

', fromName: 'Your Company Name', // optional: custom sender name cc: ['cc@example.com'], // optional: carbon copy recipients bcc: ['bcc@example.com'], // optional: blind carbon copy recipients replyTo: 'reply@example.com', // optional: reply-to address attachments: [ // optional: array of attachments (max 10, each up to 15MB) { filename: 'document.pdf', url: 'https://example.com/path/to/document.pdf', contentType: 'application/pdf' // optional }, { filename: 'image.png', url: 'https://example.com/path/to/image.png', contentType: 'image/png' // optional } ] }; const result = await totalumClient.email.sendEmail(emailPayload); ``` ## Send an email with files from Totalum storage If you have uploaded files to Totalum and want to send them as attachments, you need to get their download URLs first: ```javascript // First, get the download URL of the file uploaded to Totalum const fileNameId = 'your_file_name.pdf'; // the file name ID from Totalum const fileUrlResult = await totalumClient.files.getDownloadUrl(fileNameId); const fileUrl = fileUrlResult.data; // Then, send the email with the attachment const emailPayload = { to: ['recipient@example.com'], subject: 'Email with attachment from Totalum', html: '

Hello

Please find the attached document

', attachments: [ { filename: 'document.pdf', url: fileUrl, contentType: 'application/pdf' } ] }; const result = await totalumClient.email.sendEmail(emailPayload); ``` ## Important notes - **Maximum attachments**: 10 attachments per email - **Maximum size per attachment**: 15MB - **Attachment URLs**: All attachments must be provided as valid HTTP/HTTPS URLs - **HTML content**: You can use full HTML and CSS in the email body - **Recipients**: The `to` field must be an array of email addresses --- # ./docs/api/subirArchivos.md --- title: Upload and Download Files sidebar_position: 7 --- # Upload and Download Files --- **📚 Setup Required:** For installation and usage of the Totalum SDK or API, see the [Installation Guide](/docs/api/instalacion). --- In Totalum, you can upload files and link them to your data. For example, you can upload a PDF file and link it to a client, or upload an image and link it to a product. To do this, when creating a table, for example a `client` table, you can add a property of type `file`, and when creating or editing a client, you will be able to upload a file and link it to the client. ## 1. Upload the file to Totalum To scan a document, first you need to upload the file to Totalum. You can do this using the Totalum API directly or using the Totalum SDK. ### 1.1 Transform the file to a blob If you are not using javascript, you will need to do this step using the language you are using. Search on internet how to transform a file to a blob in your language. Or also you can ask chatgpt to transform the following examples to your language. Depending on the platform you are using, you will need to transform the file to a blob. Here are some examples: #### From a file input (Frontend) ```javascript const fileInput = document.getElementById('fileInput'); const fileBlob = fileInput.files[0]; ``` #### From a file in storage (Backend) ```javascript const fs = require('fs'); const yourFilePath = 'your_file_path'; // example: /user/your_file.pdf const fileBlob = fs.readFileSync(yourFilePath); ``` #### From a remote file (Backend) ```javascript const response = await axios.get('your_file_url', { responseType: 'stream' }); const fileBlob = response.data; ``` #### From a base64 string (Frontend/Backend) ```javascript // Convert base64 to binary const binaryStr = atob(base64String); const len = binaryStr.length; const bytes = new Uint8Array(len); for (let i = 0; i < len; i++) { bytes[i] = binaryStr.charCodeAt(i); } let fileBlob; // Environment check: Node.js or Browser if (typeof process === 'object' && process.version) { // Node.js environment // Convert Uint8Array to Buffer for Node.js usage const buffer = Buffer.from(bytes.buffer); // Here, 'buffer' can be used similarly to how you'd use a Blob in the browser // Note: Direct Blob emulation isn't possible in Node.js, but Buffer is a close alternative for file handling fileBlob = buffer; } else { // Browser environment // Create a Blob from the Uint8Array const blob = new Blob([bytes], { type: fileType }); fileBlob = blob; } ``` ### 1.2 Upload the file to Totalum **Using Totalum SDK** ```javascript const FormData = require('form-data'); // if you are using node.js const fileName = 'your_file_name.png'; // replace 'your_file_name' with the name of your file, replace .png with the extension of your file const file = yourFileBlob // your blob file created in the previous step const formData = new FormData(); formData.append('file', file, fileName); const result = await totalumClient.files.uploadFile(formData); const fileNameId = result.data; ``` **Using Totalum API** ```javascript const FormData = require('form-data'); // if you are using node.js const fileName = 'your_file_name.png'; // replace 'your_file_name' with the name of your file, replace .png with the extension of your file const file = yourFileBlob // your blob file created in the previous step const formData = new FormData(); formData.append('file', file, fileName); const result = await axios.post('https://api.totalum.app/files/upload', formData, { headers: { 'Content-Type': 'multipart/form-data', 'api-key': 'your api key here', // replace 'your api key here' with your api key } }); const fileNameId = result.data; ``` ### Upload a file to Totalum and link it to an item property ```javascript const fileName = 'your_file_name.png'; const file = yourFileBlob formData.append('file', file, fileName); const result = await totalumClient.files.uploadFile(formData); const fileNameId = result.data; //if you want to link this file to an item, you need to add the fileNameId to the item property of type file const result2 = await totalumClient.crud.editRecordById('your_element_table_name', 'your_item_id', {'your_file_property_name': {name: fileNameId}}); // now the file is linked to the item property, and you can see it in the totalum panel. //what happens if your_file_property_name is a multiple file property? const result2 = await totalumClient.crud.editRecordById('your_element_table_name', 'your_item_id', [{'your_file_property_name': {name: fileNameId}}]); // in this case, you must set an array of files, but if you don't want to lost existing files, you can set the existing files in the array and add the new file at the end of the array ``` **example:** Imagine you have a table called `client` with the following properties: - `name` (text) - `email` (text) - `phone` (text) - `photo` (file) And you want to create a new client with name `John Doe`, the email `jhon@gmail.com`, the phone `+34 123 456 789`, and the birthday `1990-01-01`, and you want to link a photo to the client. ```javascript // first, we upload the file const fileName = 'your_file_name.png'; const file = yourFileBlob formData.append('file', file, fileName); const result = await totalumClient.files.uploadFile(formData); const fileNameId = result.data; // then, we create the client const tableElementName = 'client'; const clientToCreate = { name: 'John Doe', email: 'jhon@gmail.com', phone: '+34 123 456 789', photo: { name: fileNameId } }; const result2 = await totalumClient.crud.createRecord(tableElementName, clientToCreate); // now the client is created and the photo is linked to the client //what happens if your_file_property_name is a multiple file property? const clientToCreate = { name: 'John Doe', email: 'jhon@gmail.com', phone: '+34 123 456 789', photo: [{ name: fileNameId }] }; // in this case, you must set an array of files, but if you don't want to lost existing files, you can set the existing files in the array and add the new file at the end of the array ``` ### Remove a file from Totalum ```javascript // you can remove a file from totalum using the file name id const fileNameId = 'your_file_name.png'; // replace 'your_file_name' with the name id of your file, replace .png with the extension of your file const result = await totalumClient.files.deleteFile(fileNameId); ``` #### If you want to remove a file linked to an item property, you can do it like this: ```javascript const tableElementName = 'client'; let your_item_id = '5f9b2b1b9c6f6b0001a3b2b1'; const result = await totalumClient.crud.editRecordById(tableElementName, your_item_id, {'photo': null}); // this will remove the photo from the client with id '5f9b2b1b9c6f6b0001a3b2b1' ``` ### Download a file from Totalum ```javascript // you can get the fileNameId from the result of the upload file function const fileNameId = 'your_file_name.png'; // replace 'your_file_name' with the name id of your file, replace .png with the extension of your file //optional options const options = { // the default expiration time is 128 hours, but you can set it to whatever you want, after the expiration time the url will not return the file expirationTime: Date.now() + (128 * 60 * 60 * 1000); // Set to expire in 128 hours, how it works is, set the current date in milliseconds + the milliseconds you want the url to expire } const result = await totalumClient.files.getDownloadUrl(fileNameId, options); let fileUrl = result.data; // the result will be a full url that you can use to download the file ``` ### Download a file linked to an item property **PD: usually, when you link a file to an item property, the property automatically generates a file url that you can use to download the file.** You can access the file linked to an item property in this way: Imagine you have a table called `client` with the following properties: - `name` (text) - `email` (text) - `phone` (text) - `photo` (file) And you want to download the photo of the client with id `5f9b2b1b9c6f6b0001a3b2b1`. ```javascript const tableElementName = 'client'; let clientId = '5f9b2b1b9c6f6b0001a3b2b1'; const result = await totalumClient.crud.getRecordById(tableElementName, clientId); const client = result.data; let clientPhotoUrl = client.photo.url; // this is the url of the photo, you can use it to download the photo // but in some cases, if you want to get a new temporal url to download the file, you can do it like this: const clientPhotoId = client.photo.name; const result2 = await totalumClient.files.getDownloadUrl(clientPhotoId); let fileUrl = result2.data; ``` --- # ./docs/api/creacion-pdf.mdx --- title: PDF Creation sidebar_position: 102 --- # PDF Creation Totalum allows you to create fully customizable and dynamic PDFs from HTML. --- **📚 Setup Required:** For installation and usage of the Totalum SDK or API, see the [Installation Guide](/docs/api/instalacion). --- ## Create a PDF from pure HTML If you want to create a PDF directly from HTML without creating a template first, you can use the `createPdfFromHtml` function. ```javascript const htmlContent = '

Hello World

This is a PDF created from HTML

'; const fileName = 'my-generated-pdf.pdf'; // replace with your desired file name const result = await totalumClient.files.createPdfFromHtml({ html: htmlContent, name: fileName }); const fileResult = result.data.data; // fileResult contains the generated PDF file information // if you want to link this pdf to an item, you need to add the fileName to the item property of type file const result2 = await totalumClient.crud.editItemById('your_element_table_name', 'your_item_id', {'your_pdf_property_name': {name: fileResult.fileName}}); ``` **Note:** The HTML is automatically encoded to base64 by the SDK before sending it to the API. --- ## DEPRECATED: Video Tutorial and Handlebars Approach :::caution DEPRECATED The following video tutorial and Handlebars-based approach are deprecated. Please use the "Create a PDF from pure HTML" method above instead. :::
--- # ./docs/api/usar-chatgpt.md --- title: Use OpenAI (ChatGPT, Image Generation) sidebar_position: 103 --- # Use OpenAI (ChatGPT, Image Generation) Totalum allows you to use OpenAI's API without the need to register for an OpenAI account. You can use it directly through the Totalum SDK or API. --- **📚 Setup Required:** For installation and usage of the Totalum SDK or API, see the [Installation Guide](/docs/api/instalacion). --- **No need to register on OpenAI** — Totalum handles the API access for you. ## Chat Completion ### Create a chat completion ```javascript //body the openai chat completion body, more info here: https://platform.openai.com/docs/api-reference/chat/create const bodyExample={ // see the openai api docs for more info messages: [ {content: 'You are a math specialist assistant', role: 'system'}, {content: 'how I can resolve a matrix', role: 'user'} //etc... ], model: 'gpt-4.1-mini', max_tokens: 200, } const result = await totalumClient.openai.createChatCompletion(bodyExample); const chatCompletion = result.data; // returns the completion provided by openai api ``` --- ## Image Generation Generate images from text prompts using OpenAI's image generation model. ### Generate an image ```javascript const result = await totalumClient.openai.generateImage({ prompt: 'A professional product photo of a red sneaker on a white background', fileName: 'red-sneaker', size: '1024x1024', // optional: '1024x1024', '1536x1024' (landscape), '1024x1536' (portrait), 'auto' quality: 'low', // optional: 'low' (fastest), 'medium', 'high', 'auto' output_format: 'png', // optional: 'png', 'jpeg', 'webp' background: 'auto' // optional: 'transparent' (requires png), 'opaque', 'auto' }); const { fileName, imageUrl } = result.data; // fileName: the file ID stored in Totalum (e.g. 'abc123.png') // imageUrl: a signed URL to directly access the generated image ``` **Minimal example:** ```javascript const result = await totalumClient.openai.generateImage({ prompt: 'A cute cartoon cat', fileName: 'cartoon-cat' }); const { fileName, imageUrl } = result.data; console.log('Image URL:', imageUrl); ``` ### Generate an image with transparent background ```javascript const result = await totalumClient.openai.generateImage({ prompt: 'A company logo with the letter T in blue', fileName: 'logo', background: 'transparent', output_format: 'png' // transparent requires png format }); const { fileName, imageUrl } = result.data; ``` --- ## Image Editing Edit or transform existing images using OpenAI's image editing model. You can: - Edit parts of an image (e.g. change clothes while keeping the face) - Use images as style references - Combine multiple images - Apply masked editing ### Edit an image ```javascript const result = await totalumClient.openai.editImage({ prompt: 'Change ONLY the clothing to a blue suit. Keep the face, hair, and background EXACTLY the same.', imageUrls: ['https://example.com/photo.jpg'], // 1-16 image URLs fileName: 'edited-photo', input_fidelity: 'high', // 'high' preserves details (faces, features) — use for editing. 'low' allows creative freedom — use for style references. size: '1024x1024', // optional quality: 'low', // optional output_format: 'png' // optional }); const { fileName, imageUrl } = result.data; // fileName: the file ID stored in Totalum // imageUrl: a signed URL to the edited image ``` ### Combine multiple images ```javascript const result = await totalumClient.openai.editImage({ prompt: 'Combine these two images into a single scene: place the person from the first image in the landscape from the second image', imageUrls: [ 'https://example.com/person.jpg', 'https://example.com/landscape.jpg' ], fileName: 'combined-scene', input_fidelity: 'low' // 'low' for creative combination }); const { fileName, imageUrl } = result.data; ``` ### Use an image as style reference ```javascript const result = await totalumClient.openai.editImage({ prompt: 'Create a new product photo in the same visual style as the reference image, but showing a blue backpack', imageUrls: ['https://example.com/style-reference.jpg'], fileName: 'styled-product', input_fidelity: 'low' // 'low' for style transfer }); const { fileName, imageUrl } = result.data; ``` ### Use the generated image in a Totalum record After generating or editing an image, you can attach it to a record's file property: ```javascript // 1. Generate the image const imageResult = await totalumClient.openai.generateImage({ prompt: 'Professional headshot photo', fileName: 'headshot' }); // 2. Use the fileName to attach it to a record's file property await totalumClient.crud.editRecordProperties('employee', employeeId, { profile_photo: { name: imageResult.data.fileName } }); ``` --- # ./docs/api/scanDocuments/scanDocuments.md # Scan Documents This is the documentation for the scan documents. With Totalum scan documents you can scan your custom documents and extract JSON data from them. Totalum scan documents only works with images and PDF files. It can scan any image or pdf with any format and extract the data you want. It works with machine learning to extract the data from the documents. You can use TotalumSdk for javascript or use the Totalum API directly. If you chose to use TotalumSdk, Please check the previous installation step to see how to install the TotalumSdk. ## Video Tutorial
## 1. Upload the file to Totalum To scan a document, first you need to upload the file to Totalum. You can do this using the Totalum API directly or using the Totalum SDK. ### 1.1 Transform the file to a blob If you are not using javascript, you will need to do this step using the language you are using. Search on internet how to transform a file to a blob in your language. Or also you can ask chatgpt to transform the following examples to your language. Depending on the platform you are using, you will need to transform the file to a blob. Here are some examples: #### From a file input (Frontend) ```javascript const fileInput = document.getElementById('fileInput'); const fileBlob = fileInput.files[0]; ``` #### From a file in storage (Backend) ```javascript const fs = require('fs'); const yourFilePath = 'your_file_path'; // example: /user/your_file.pdf const fileBlob = fs.readFileSync(yourFilePath); ``` #### From a remote file (Backend) ```javascript const response = await axios.get('your_file_url', { responseType: 'stream' }); const fileBlob = response.data; ``` #### From a base64 string (Frontend/Backend) ```javascript // Convert base64 to binary const binaryStr = atob(base64String); const len = binaryStr.length; const bytes = new Uint8Array(len); for (let i = 0; i < len; i++) { bytes[i] = binaryStr.charCodeAt(i); } let fileBlob; // Environment check: Node.js or Browser if (typeof process === 'object' && process.version) { // Node.js environment // Convert Uint8Array to Buffer for Node.js usage const buffer = Buffer.from(bytes.buffer); // Here, 'buffer' can be used similarly to how you'd use a Blob in the browser // Note: Direct Blob emulation isn't possible in Node.js, but Buffer is a close alternative for file handling fileBlob = buffer; } else { // Browser environment // Create a Blob from the Uint8Array const blob = new Blob([bytes], { type: fileType }); fileBlob = blob; } ``` ### 1.2 Upload the file to Totalum **Using Totalum SDK** ```javascript const FormData = require('form-data'); // if you are using node.js const fileName = 'your_file_name.png'; // replace 'your_file_name' with the name of your file, replace .png with the extension of your file const file = yourFileBlob // your blob file created in the previous step const formData = new FormData(); formData.append('file', file, fileName); const result = await totalumClient.files.uploadFile(formData); const fileNameId = result.data; ``` **Using Totalum API** ```javascript const FormData = require('form-data'); // if you are using node.js const fileName = 'your_file_name.png'; // replace 'your_file_name' with the name of your file, replace .png with the extension of your file const file = yourFileBlob // your blob file created in the previous step const formData = new FormData(); formData.append('file', file, fileName); const result = await axios.post('https://api.totalum.app/api/v1/files/upload', formData, { headers: { 'Content-Type': 'multipart/form-data', 'api-key': 'your api key here', // replace 'your api key here' with your api key } }); const fileNameId = result.data.data; ``` ## 2. Scan the document **Using Totalum SDK** ```javascript // last steps here const result = await totalumClient.files.uploadFile(formData); const fileNameId = result.data; // this properties are just an example, you need to replace them with the properties that you want to extract from your document const properties = { "name": { "type": "string", "description": "the name visible in the top of document" }, "born": { "type": "string", "format": "date", "description": "The date of birth of the person in the document" }, "total": { "type": "number", "description": "the total amount of that the person has to pay in the document" }, "currency": { "type": "string", "enum": ["EUR", "USD", "GBP", "OTHER"], "description": "the currency of the total amount in the document, set to 'OTHER' if the currency is not in the list" } } const scanResult = await totalumClient.files.scanDocument(fileNameId, properties); const scanData = scanResult.data; console.log(scanData); ``` **Using Totalum API** ```javascript // last steps here const result = await axios.post('https://api.totalum.app/api/v1/files/upload', formData, { headers: { 'Content-Type': 'multipart/form-data', 'api-key': 'your api key here', // replace 'your api key here' with your api key } }); const fileNameId = result.data.data; const properties = { // see the example of before } const scanResult = await axios.post('https://api.totalum.app/api/v1/files/scan-document', { "fileName": fileNameId, "properties": properties }, { headers: { 'Content-Type': 'application/json', 'api-key': 'your api key here', // replace 'your api key here' with your api key } }); const scanData = scanResult.data.data; console.log(scanData); ``` ### 2.1 Properties The properties object is a JSON object that describes the data you want to extract from the document following json schema format. The keys of the object are the names of the properties you want to extract, and the values are objects that describe the type of the property and other details. #### 2.1.1 How it works ```javascript const properties = { "propertyName": { "type": "property type", "description": "property description" }, // you can add more properties here // etc... } ``` **propertyName** is the name of the property you want to extract from the document. You can name it as you want. **type** is the type of the property you want to extract. It can be "string", "number", "enum", "array", "object" **description** is a description of the property you want to extract. You can write here any description you want. The description helps the machine learning model to extract the data from the document. ##### get a string from the document ```javascript "someString": { // replace 'someString' with the name you need "type": "string", "description": "your description" } ``` ##### get a Date from the document ```javascript "someDate": { // replace 'someDate' with the name you need "type": "string", "format": "date", "description": "your description" } ``` ##### get a number from the document ```javascript "someNumber": { // replace 'someNumber' with the name you need "type": "number", "description": "your description" } ``` ##### get an enum from the document ```javascript "someEnum": { // replace 'someEnum' with the name you need "type": "string", "enum": ["EUR", "USD", "GBP", "OTHER"], // replace with the values you need "description": "your description" } ``` ##### get an array of strings from the document ```javascript "someArray": { // replace 'someArray' with the name you need "type": "array", "description": "your description", "items": { type: "string", description: "your description" } } ``` ##### get an array of objects from the document ```javascript "someArray": { // replace 'someArray' with the name you need "type": "array", "description": "your description", "items": { type: "object", properties: { rowName: { // replace 'rowName' with the name you need type: "string", description: "your description" } } } } ``` ### 2.2 Properties examples REMEMBER: YOU CAN SCAN ANY KIND OF DOCUMENT, YOU ONLY NEED TO DESCRIBE THE PROPERTIES YOU WANT TO EXTRACT FROM THE DOCUMENT. ##### Scan a passport (Pasaporte) ```javascript const properties = { "name": { "type": "string", "description": "the name of the person in the document" }, "nationality": { "type": "string", "description": "the nationality of the person in the document" }, "passportNumber": { "type": "string", "description": "the passport number of the person in the document" }, "birthDate": { "type": "string", "format": "date", "description": "the birth date of the person in the document" }, "expirationDate": { "type": "string", "format": "date", "description": "the expiration date of the person in the document" } } ``` ##### Scan a college degree (Título Universitario) ```javascript const properties = { "name": { "type": "string", "description": "the name of the person in the document" }, "degree": { "type": "string", "description": "the degree of the person in the document" }, "university": { "type": "string", "description": "the university of the person in the document" }, "graduationDate": { "type": "string", "format": "date", "description": "the graduation date of the person in the document" }, "registrationNumber": { "type": "string", "description": "the registration number of the person in the document" } } ``` ### 2.3 Configuration options #### model models available: `scanum`, `scanum-pro`, `scanum-eye-pro` (scanum is the default model, it's a general model for documents and for extract a lot of data, scanum-eye-pro has the capacity of detect colors, shapes and understand the image, scanum-eye-pro the same as scanum-eye but with more capacity of understand the image, also is more expensive) Scanum eye pro only works with images. And its a good choice if you have a complex image with a lot of shapes and colors. Or the text is a little bit hard to extract (is not in a straight line, or is not in a good quality). Scanum and Scanum pro models works with images and PDF files. It's a general model that works with a lot of documents. It's a good choice if you have a simple document with text in a straight line. Also is better for large text extraction. The difference between scanum and scanum-pro is that scanum-pro is a little more intelligent for extract the text, but the vision capabilities are the same. Also scanum-pro is more expensive than scanum. #### removeFileAfterScan (boolean) set to true if you want to remove the file after the scan. If is true, after the scan the file will be removed forever. #### returnOcrFullResult (boolean) set to true if you want to return the full OCR result. The OCR result contains a big JSON with all text extracted from the document, including all coordinates of every word and every character. Also includes all text inline. #### maxPages (number) set the maximum number of pages to scan in a PDF file Example: if you set maxPages to 5, and the PDF file has 10 pages, only the first 5 pages will be scanned. #### pdfPages (array of numbers) set the pages to scan in a PDF file. Example: [1, 5, 10] (only pages 1, 5 and 10 will be scanned) #### scanDescription (string) set a additional description for add more context to what to scan and how to obtain it. Example: "The file is an invoice and the Invoice Issuer company is Apple Inc." #### processEveryPdfPageAsDifferentScan (boolean) set to true if you want to process every page of a PDF as a different scan (the result will be an array of objects) If you have a PDF with 3 pages and you set this option to true, the result will be an array with 3 objects, each object will contain the data extracted from each page. Example: Imagine you have a PDF with 3 pages, and every page contains a different invoice. If you set this option to true, you will get an array with 3 objects, each object will contain the data extracted from each invoice. If is false, you will get only one object with the data extracted from the 3 invoices (data can wrong or mixed). ### 2.3.1 How to add configuration options Its easy, just add a **options** field with a json with the configuration that you want. ** Using Curl ** ```bash curl -X POST https://api.totalum.app/api/v1/files/scan-document \ -H 'Content-Type: application/json' \ -H 'api-key: your api key here' \ -d '{ "fileName": "your_file_name_id", "properties": { // your properties here }, "options": { "model": "scanum", "removeFileAfterScan": false, "returnOcrFullResult": false, "maxPages": 5, "pdfPages": [1,2,3], "scanDescription": "The file is an invoice and the Invoice Issuer company is Apple Inc.", "processEveryPdfPageAsDifferentScan": false } }' ``` **Using Totalum SDK** ```javascript // last steps here const options = { model: 'scanum', removeFileAfterScan: false, returnOcrFullResult: false, maxPages: 5, pdfPages: [1,2,3], scanDescription: "The file is an invoice and the Invoice Issuer company is Apple Inc.", processEveryPdfPageAsDifferentScan: false } const scanResult = await totalumClient.files.scanDocument(fileNameId, properties, options); ``` **Using Totalum API in Javascript** ```javascript // last steps here const options = { model: 'scanum', removeFileAfterScan: false, returnOcrFullResult: false, maxPages: 5, pdfPages: [1, 2, 3], scanDescription: "The file is an invoice and the Invoice Issuer company is Apple Inc.", processEveryPdfPageAsDifferentScan: false } const scanResult = await axios.post('https://api.totalum.app/api/v1/files/scan-document', { "fileName": fileNameId, "properties": properties, "options": options }, { headers: { 'Content-Type': 'application/json', 'api-key': 'your api key here', // replace 'your api key here' with your api key } }); ``` --- # ./docs/admin-panel/notifications.md --- title: Notifications sidebar_position: 7 --- # How to send notifications to users of Totalum Important consideration: this notification will be sent to users of totalum backoffice, not to users of your own application that uses Totalum SDK or API. ### 1. What are notifications in Totalum? A Totalum notification, sends an email to all or some of the users of your Totalum that you want to notify with a custom text. Also, the user can see the notification visually in their Totalum account. ### 2. How to send notifications to users of Totalum #### 2.1 body of the notification The notification object has the following structure: ```javascript interface NotificationI { name: string; title: string; description: string; visibility: { sendTo: 'all' | 'admins' | 'specificUsers'; // "all" will send the notification to all users of Totalum, "admins" will send the notification to all admins of Totalum, "specificUsers" will send the notification to the users that you specify in the field specificUsersEmails specificUsersEmails?: string[]; // this field is only required if sendTo is 'specificUsers' (put here the list of emails of the users you want to send the notification to) }, action: { actionType: 'link' | 'none'; //put link if you want to set a button clickable that opens the link in the Totalum account actionName?: string; link?: string; }; email: { sendEmail: boolean; //put it true if you want to send an email to the users, else put it false and the users will only see the notification in their Totalum account }; } ``` **Using Totalum SDK** If you don't have the Totalum SDK installed, follow the instructions in the [installation section](/docs/api/instalacion). ```javascript const notification = { name: "your notification name", title: "Your Notification Title", description: "The text that you want to send to the users", visibility: { sendTo: "all", specificUsersEmails: [] }, action: { actionType: "link", actionName: "activar", link: "https://www.google.com/" //put custom link if needed }, email: { sendEmail: true, } }; const resultCreation = await totalumClient.notification.createNotification(notification); ``` **Using Totalum API** This is an example using javascript and axios, but you can use any language and library to make the request. ```javascript const notification = { name: "your notification name", title: "Your Notification Title", description: "The text that you want to send to the users", visibility: { sendTo: "all", specificUsersEmails: [] }, action: { actionType: "link", actionName: "activar", link: "https://www.google.com/" //put custom link if needed }, email: { sendEmail: true, } }; const resultCreation = await axios.post('https://api.totalum.app/api/v1/notifications/', {notification: notification}, { headers: { 'Content-Type': 'application/json', 'api-key': 'your api key here', // replace 'your api key here' with your api key } }); ``` ---