# API Maker Documentation : Code examples > The pages of https://docs.apimaker.dev in the order of the navigation, each with its title, its description and its URL. The code is in TypeScript : the Markdown of a page (its URL with .md) has every language. --- # Code Examples > A working example, in TypeScript, Python, PHP, C#, Go, Rust, Java and Kotlin, of every method your code can call in API Maker - g.sys.db and g.sys.db.gen for the database APIs, g.sys.system, g.sys.cache, the request and response objects, the shared space and the logger. Source: https://docs.apimaker.dev/v4/examples/index.html Custom APIs, hooks, events, schedulers, migrations, process initializers and test cases all receive the same [global object `g`](https://docs.apimaker.dev/v4/docs/pre-defined-terms/global-object-g.html). Every page of this section is one method of it, with examples you can paste into the editor of the admin panel, in every [language](https://docs.apimaker.dev/v4/docs/languages/index.html) : pick yours in the tabs, and every page shows it from then on. Every piece of code is the function `main` of its language ; the examples are the inside of it : **TypeScript** ```typescript import * as T from 'types'; // the types of API Maker import * as db from 'db-interfaces'; // the interfaces generated from your schemas async function main(g: T.IAMGlobal) { // your code, with await on every call of g.sys return { hello: 'world' }; // what the caller receives in data } module.exports = main; ``` Every language gets the same `g`, written the way the language writes things (`g.sys.db.get_all` in Python, `g.Sys.Db.GetAll` in C# and Go) : see [Languages and runtimes](https://docs.apimaker.dev/v4/docs/languages/index.html). - [g.sys.db](https://docs.apimaker.dev/v4/examples/sys/db/getAll.html) : The 17 schema APIs of a table, from get all to distinct with query. - [g.sys.db.gen](https://docs.apimaker.dev/v4/examples/sys/db/getAll.html#without-a-schema) : The same operations without the schema. - [g.sys.system](https://docs.apimaker.dev/v4/examples/sys/system/system.html) : Encrypt, hash, tokens, secrets, queries, indexes, events, validation, external calls. - [g.sys.cache](https://docs.apimaker.dev/v4/docs/apis-all/system-apis/system-generated-set-redis-key-api.html#from-code) : Redis keys and cache resets. - [g.req](https://docs.apimaker.dev/v4/examples/req/req.html#body) : Body, headers, params, query params, event data and the tokens of the caller. - [g.res](https://docs.apimaker.dev/v4/examples/res/res.html#output) : Output, status code, errors, warnings, content type. - [Custom API](https://docs.apimaker.dev/v4/examples/custom-apis/custom-api.html) : A complete custom API, from the settings to the code. - [g.logger and g.shared](https://docs.apimaker.dev/v4/docs/pre-defined-terms/global-object-g.html#glogger-and-gshared) : Logs which reach the caller and the log table, and values shared between hooks. > **Tip : The whole envelope** > > A `g.sys` call returns `data` and throws the errors, so the caller of your API gets them. The whole [response envelope](https://docs.apimaker.dev/v4/docs/apis-all/response-format.html), which never throws, comes with `true` as the second argument in TypeScript (`const res = await g.sys.db.count({ ... }, true); if (!res.success) ...`), and through `full` in the other languages (`res = await g.sys.db.full.count(...)` in Python, `g.Sys.Db.Full.Count(...)` in C# and Go). (The code of this page is also written in Python, PHP, C#, Go, Rust, Java, Kotlin : https://docs.apimaker.dev/v4/examples/index.md) --- # Get All > Retrieve all records from a specified collection in your database using API Maker's `g.sys.db.getAll` method. Source: https://docs.apimaker.dev/v4/examples/sys/db/getAll.html > **The code in every language** > > Each example is the inside of `main`, written in every [language](https://docs.apimaker.dev/v4/docs/languages/index.html) API Maker runs : pick yours in the tabs, and every page shows it from then on. The types a call takes (`GetAll`, `DeepItem`…) are those of `am` : `from am import GetAll` in Python, `use am::GetAll;` in Rust, `import am.GetAll;` in Java and Kotlin ; PHP and C# have them without an import, Go names them `am.GetAll`. `g.sys.db.getAll` calls the [get all schema API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-get-all-api.html) of any table from your code, with the same headers and query parameters as over HTTP. It returns the data. The whole envelope (`success`, `statusCode`, `data`, `totalCount`, `errors`…) comes back when `true` is passed as the second argument in TypeScript, and through `full` in the other languages : `g.sys.db.full` (`g.Sys.Db.Full` in C# and Go, `$g->sys->db->full` in PHP). ## Get all data **TypeScript** **Get all data from table 'customers'** ```typescript let getAll = await g.sys.db.getAll({ instance: "mysql_8", database: "inventory", collection: "customers", }); ``` ## With header **TypeScript** **Get all with header** ```typescript let getAll = await g.sys.db.getAll({ instance: "mysql_8", database: "inventory", collection: "customers", headers: { "x-am-response-case": "capitalCase", // noChange | camelCase | capitalCase | constantCase | dotCase | headerCase | noCase | paramCase | pascalCase | pathCase | sentenceCase | snakeCase }, }); ``` ## With queryParams **TypeScript** **Get all with queryParams** ```typescript let getAll = await g.sys.db.getAll({ instance: "mysql_8", database: "inventory", collection: "customers", queryParams: { find: { first_name: 'James', }, }, }, true); ``` ## Every header and query param **TypeScript** **Structure of get all schema API** ```typescript let getAll = await g.sys.db.getAll({ instance: "INSTANCE_NAME", database: 'DB_NAME', collection: "COLLECTION_NAME", headers: { "x-am-response-case": "capitalCase", // noChange | camelCase | capitalCase | constantCase | dotCase | headerCase | noCase | paramCase | pascalCase | pathCase | sentenceCase | snakeCase "x-am-response-object-type": "make_flat", // no_action | make_flat "x-am-meta": "true", // true, false "x-am-internationalization": "USER_I18N_ID", "x-am-run-in-sandbox": "2", "x-am-content-type-response": "text/xml", // application/json | text/xml | text/yaml | text/plain | text/html | application/octet-stream "x-am-cache-control": "reset_cache", // no_action | reset_cache "x-am-get-encrypted-data": "get_only_encryption", // no_encryption | get_only_encryption | get_data_and_encryption "x-am-sandbox-timeout": "13000", "x-no-compression": "true", // true | false "x-am-encrypted-payload": "true", // user will send 'true', when payload is encrypted for transfer // Multi-tenant : the tenant of the request, each instance finds it in its own tenants table "x-am-tenant-username": "TENANT_USERNAME", // ex: acme // Authorization headers "x-am-authorization": "AUTHORIZATION_TOKEN", "x-am-user-authorization": "API_USER_TOKEN", "x-aws-authorization": "AWS_TOKEN", "x-google-authorization": "GOOGLE_TOKEN", "x-azure-authorization": "AZURE_TOKEN", }, queryParams: { find: { "COLUMN_NAME": "COLUMN_VALUE" }, skip: 1, limit: 5, sort: "COLUMN_NAME", select: "COMMA_SEPARATED_COLUMN_NAMES", getTotalCount: true, deep: [ { s_key: "SOURCE_COLLECTION_COLUMN_NAME", t_instance: "TARGET_INSTANCE_NAME", t_db: "TARGET_DATABASE_NAME", t_col: "TARGET_COLLECTION_NAME", t_key: "TARGET_COLLECTION_COLUMN_NAME", find: { "COLUMN_NAME": "COLUMN_VALUE" }, isMultiple: true, limit: 10, select: "COMMA_SEPARATED_COLUMN_NAMES", skip: 2, sort: "COLUMN_NAME", deep: [ { s_key: "SOURCE_COLLECTION_COLUMN_NAME", t_instance: "TARGET_INSTANCE_NAME", t_db: "TARGET_DATABASE_NAME", t_col: "TARGET_COLLECTION_NAME", t_key: "TARGET_COLLECTION_COLUMN_NAME", find: { "COLUMN_NAME": "COLUMN_VALUE" }, isMultiple: true, limit: 10, select: "COMMA_SEPARATED_COLUMN_NAMES", skip: 2, sort: "COLUMN_NAME", } ] } ] }, }, true); ``` ## Multi-tenant - `instance: "crm::acme"` works on the database of the tenant `acme` of the [multi-tenant](https://docs.apimaker.dev/v4/docs/features/multi-tenant.html) instance `crm`. - With `instance: "crm"`, the call works on the database of the tenant of the request: a custom API called with the [x-am-tenant-username](https://docs.apimaker.dev/v4/docs/apis-all/header/requestHeader.html#x-am-tenant-username) header passes it on to the APIs it calls. A request without a tenant works on the structure database. **TypeScript** **Get all customers of the tenant acme** ```typescript let getAll = await g.sys.db.getAll({ instance: "crm::acme", database: "crm", collection: "customers", queryParams: { sort: "customer_id" } }); ``` **TypeScript** **Get all customers of the tenant globex, named with the header of the call** ```typescript let getAll = await g.sys.db.getAll({ instance: "crm", database: "crm", collection: "customers", headers: { "x-am-tenant-username": "globex" } }); ``` ## Without a schema `g.sys.db.gen.getAllGen` takes the same arguments and calls the [get all generated API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-get-all-api.html#without-a-schema) : no schema, so the data is read and written as it is in the table, without the conversions, validations and defaults of the schema. | Language | The call | |---|---| | TypeScript | `g.sys.db.gen.getAllGen(…)` | | Python | `g.sys.db.gen.get_all_gen(…)` | | PHP | `$g->sys->db->gen->getAllGen(…)` | | C#, Go | `g.Sys.Db.Gen.GetAllGen(…)` | | Rust | `g.sys.db.get_all_gen(GetAll::new(…))` | | Java, Kotlin | `g.sys.db.gen.getAllGen(…)` | ## Related - [Get all API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-get-all-api.html) · [Generated API from code](https://docs.apimaker.dev/v4/examples/sys/db/getAll.html#without-a-schema) · [The global object g](https://docs.apimaker.dev/v4/docs/pre-defined-terms/global-object-g.html) (The code of this page is also written in Python, PHP, C#, Go, Rust, Java, Kotlin : https://docs.apimaker.dev/v4/examples/sys/db/getAll.md) --- # Get All by Stream > Fetch all records from a collection in a streaming manner, useful for handling large datasets efficiently. Source: https://docs.apimaker.dev/v4/examples/sys/db/getAllByStream.html > **The code in every language** > > Each example is the inside of `main`, written in every [language](https://docs.apimaker.dev/v4/docs/languages/index.html) API Maker runs : pick yours in the tabs, and every page shows it from then on. The types a call takes (`GetAll`, `DeepItem`…) are those of `am` : `from am import GetAll` in Python, `use am::GetAll;` in Rust, `import am.GetAll;` in Java and Kotlin ; PHP and C# have them without an import, Go names them `am.GetAll`. `g.sys.db.getAllByStream` calls the [get all by stream schema API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-get-all-by-stream-api.html) of any table from your code, with the same headers and query parameters as over HTTP. Each row goes to your function as the database sends it, so a large table never sits in memory at once. ## Get all using stream API **TypeScript** **Get all from table** ```typescript let response = []; await g.sys.db.getAllByStream({ instance: "mysql_8", database: "inventory", collection: "customers", }, (item) => { response.push(item); }); ``` ## With header **TypeScript** **Get all with header** ```typescript let response = []; await g.sys.db.getAllByStream({ instance: "mysql_8", database: "inventory", collection: "customers", headers: { "x-am-response-case": "capitalCase", // noChange | camelCase | capitalCase | constantCase | dotCase | headerCase | noCase | paramCase | pascalCase | pathCase | sentenceCase | snakeCase }, }, (item) => { response.push(item); }); ``` ## With queryParams **TypeScript** **Get all With queryParams** ```typescript let response = []; await g.sys.db.getAllByStream({ instance: "mysql_8", database: "inventory", collection: "customers", queryParams: { select: "first_name,last_name", limit: 10, sort: "customer_id", find: { "first_name": "John" }, skip: 1, getTotalCount: true, deep: [{ s_key: "customer_id", t_key: "owner_id", t_col: "products", select: "name, description, price" }] }, }, (item) => { response.push(item); }); ``` ## Structure **TypeScript** **Get all by stream with all params** ```typescript let response = []; await g.sys.db.getAllByStream({ instance: "INSTANCE_NAME", database: 'DB_NAME', collection: "COLLECTION_NAME", headers: { "x-am-response-case": "capitalCase", // noChange | camelCase | capitalCase | constantCase | dotCase | headerCase | noCase | paramCase | pascalCase | pathCase | sentenceCase | snakeCase "x-am-response-object-type": "make_flat", // no_action | make_flat "x-am-meta": "true", // true, false "x-am-internationalization": "USER_I18N_ID", "x-am-run-in-sandbox": "2", "x-am-content-type-response": "text/xml", // application/json | text/xml | text/yaml | text/plain | text/html | application/octet-stream "x-am-cache-control": "reset_cache", // no_action | reset_cache "x-am-get-encrypted-data": "get_only_encryption", // no_encryption | get_only_encryption | get_data_and_encryption "x-am-sandbox-timeout": "13000", "x-no-compression": "true", // true | false "x-am-encrypted-payload": "true", // user will send 'true', when payload is encrypted for transfer // Multi-tenant : the tenant of the request, each instance finds it in its own tenants table "x-am-tenant-username": "TENANT_USERNAME", // ex: acme // Authorization headers "x-am-authorization": "AUTHORIZATION_TOKEN", "x-am-user-authorization": "API_USER_TOKEN", "x-aws-authorization": "AWS_TOKEN", "x-google-authorization": "GOOGLE_TOKEN", "x-azure-authorization": "AZURE_TOKEN", }, queryParams: { find: { "COLUMN_NAME": "COLUMN_VALUE" }, skip: 1, limit: 5, sort: "COLUMN_NAME", select: "COMMA_SEPARATED_COLUMN_NAMES", getTotalCount: true, deep: [ { s_key: "SOURCE_COLLECTION_COLUMN_NAME", t_instance: "TARGET_INSTANCE_NAME", t_db: "TARGET_DATABASE_NAME", t_col: "TARGET_COLLECTION_NAME", t_key: "TARGET_COLLECTION_COLUMN_NAME", find: { "COLUMN_NAME": "COLUMN_VALUE" }, isMultiple: true, limit: 10, select: "COMMA_SEPARATED_COLUMN_NAMES", skip: 2, sort: "COLUMN_NAME", deep: [ { s_key: "SOURCE_COLLECTION_COLUMN_NAME", t_instance: "TARGET_INSTANCE_NAME", t_db: "TARGET_DATABASE_NAME", t_col: "TARGET_COLLECTION_NAME", t_key: "TARGET_COLLECTION_COLUMN_NAME", find: { "COLUMN_NAME": "COLUMN_VALUE" }, isMultiple: true, limit: 10, select: "COMMA_SEPARATED_COLUMN_NAMES", skip: 2, sort: "COLUMN_NAME", } ] } ] }, }, (item) => { response.push(item); }); ``` ## Multi-tenant - `instance: "crm::acme"` works on the database of the tenant `acme` of the [multi-tenant](https://docs.apimaker.dev/v4/docs/features/multi-tenant.html) instance `crm`. - With `instance: "crm"`, the call works on the database of the tenant of the request: a custom API called with the [x-am-tenant-username](https://docs.apimaker.dev/v4/docs/apis-all/header/requestHeader.html#x-am-tenant-username) header passes it on to the APIs it calls. A request without a tenant works on the structure database. **TypeScript** **Get all customers of the tenant acme by stream** ```typescript let response = []; await g.sys.db.getAllByStream({ instance: "crm::acme", database: "crm", collection: "customers", }, (item) => { response.push(item); }); ``` ## Without a schema `g.sys.db.gen.getAllByStreamGen` takes the same arguments and calls the [get all by stream generated API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-get-all-by-stream-api.html#without-a-schema) : no schema, so the data is read and written as it is in the table, without the conversions, validations and defaults of the schema. | Language | The call | |---|---| | TypeScript | `g.sys.db.gen.getAllByStreamGen(…)` | | Python | `g.sys.db.gen.get_all_by_stream_gen(…)` | | PHP | `$g->sys->db->gen->getAllByStreamGen(…)` | | C#, Go | `g.Sys.Db.Gen.GetAllByStreamGen(…)` | | Rust | `g.sys.db.get_all_by_stream_gen(GetAll::new(…))` | | Java, Kotlin | `g.sys.db.gen.getAllByStreamGen(…)` | ## Related - [Get all by stream API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-get-all-by-stream-api.html) · [Generated API from code](https://docs.apimaker.dev/v4/examples/sys/db/getAllByStream.html#without-a-schema) · [The global object g](https://docs.apimaker.dev/v4/docs/pre-defined-terms/global-object-g.html) (The code of this page is also written in Python, PHP, C#, Go, Rust, Java, Kotlin : https://docs.apimaker.dev/v4/examples/sys/db/getAllByStream.md) --- # Get by ID > Retrieve a single record from a collection based on its unique identifier using API Maker's g.sys.db.getById method. Source: https://docs.apimaker.dev/v4/examples/sys/db/getById.html > **The code in every language** > > Each example is the inside of `main`, written in every [language](https://docs.apimaker.dev/v4/docs/languages/index.html) API Maker runs : pick yours in the tabs, and every page shows it from then on. The types a call takes (`GetAll`, `DeepItem`…) are those of `am` : `from am import GetAll` in Python, `use am::GetAll;` in Rust, `import am.GetAll;` in Java and Kotlin ; PHP and C# have them without an import, Go names them `am.GetAll`. `g.sys.db.getById` calls the [get by id schema API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-get-by-id-api.html) of any table from your code, with the same headers and query parameters as over HTTP. It returns the data. The whole envelope (`success`, `statusCode`, `data`, `totalCount`, `errors`…) comes back when `true` is passed as the second argument in TypeScript, and through `full` in the other languages : `g.sys.db.full` (`g.Sys.Db.Full` in C# and Go, `$g->sys->db->full` in PHP). ## Get by id **TypeScript** **Get by id from table** ```typescript let getById = await g.sys.db.getById({ instance: "mysql_8", database: "inventory", collection: "customers", id: 2 }); ``` ## With [primaryKey] override **TypeScript** **Get by id with primary key override** ```typescript let getById= await g.sys.db.getById({ instance: "mysql_8", database: "inventory", collection: "customers", id: "NICK", primaryKey:"first_name", }); ``` ## With header **TypeScript** **Get by id with header** ```typescript let getById = await g.sys.db.getById({ instance: "mysql_8", database: "inventory", collection: "customers", id: 2, headers: { "x-am-response-case": "capitalCase", // noChange | camelCase | capitalCase | constantCase | dotCase | headerCase | noCase | paramCase | pascalCase | pathCase | sentenceCase | snakeCase }, }); ``` ## Structure **TypeScript** **Get by id with all params** ```typescript let getById = await g.sys.db.getById({ instance: "INSTANCE_NAME", database: 'DB_NAME', collection: "COLLECTION_NAME", id: 100050, primaryKey: 'COLUMN_NAME', select: "COMMA_SEPARATED_COLUMN_NAMES", deep: [{ // string, string[], array of objects are supported s_key: "customer_id", t_key: "owner_id", t_col: "products", select: "proName,proDescription,proPrice" }], headers: { "x-am-response-case": "capitalCase", // noChange | camelCase | capitalCase | constantCase | dotCase | headerCase | noCase | paramCase | pascalCase | pathCase | sentenceCase | snakeCase "x-am-response-object-type": "make_flat", // no_action | make_flat "x-am-meta": "true", // true, false "x-am-internationalization": "USER_I18N_ID", "x-am-run-in-sandbox": "2", "x-am-content-type-response": "text/xml", // application/json | text/xml | text/yaml | text/plain | text/html | application/octet-stream "x-am-cache-control": "reset_cache", // no_action | reset_cache "x-am-get-encrypted-data": "get_only_encryption", // no_encryption | get_only_encryption | get_data_and_encryption "x-am-sandbox-timeout": "13000", "x-no-compression": "true", // true | false "x-am-encrypted-payload": "true", // user will send 'true', when payload is encrypted for transfer // Multi-tenant : the tenant of the request, each instance finds it in its own tenants table "x-am-tenant-username": "TENANT_USERNAME", // ex: acme // Authorization headers "x-am-authorization": "AUTHORIZATION_TOKEN", "x-am-user-authorization": "API_USER_TOKEN", "x-aws-authorization": "AWS_TOKEN", "x-google-authorization": "GOOGLE_TOKEN", "x-azure-authorization": "AZURE_TOKEN", }, }); ``` ## Multi-tenant - `instance: "crm::acme"` works on the database of the tenant `acme` of the [multi-tenant](https://docs.apimaker.dev/v4/docs/features/multi-tenant.html) instance `crm`. - With `instance: "crm"`, the call works on the database of the tenant of the request: a custom API called with the [x-am-tenant-username](https://docs.apimaker.dev/v4/docs/apis-all/header/requestHeader.html#x-am-tenant-username) header passes it on to the APIs it calls. A request without a tenant works on the structure database. **TypeScript** **Get the customer 1 of the tenant acme** ```typescript let getById = await g.sys.db.getById({ instance: "crm::acme", database: "crm", collection: "customers", id: 1 }); ``` ## Without a schema `g.sys.db.gen.getByIdGen` takes the same arguments and calls the [get by id generated API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-get-by-id-api.html#without-a-schema) : no schema, so the data is read and written as it is in the table, without the conversions, validations and defaults of the schema. | Language | The call | |---|---| | TypeScript | `g.sys.db.gen.getByIdGen(…)` | | Python | `g.sys.db.gen.get_by_id_gen(…)` | | PHP | `$g->sys->db->gen->getByIdGen(…)` | | C#, Go | `g.Sys.Db.Gen.GetByIdGen(…)` | | Rust | `g.sys.db.get_by_id_gen(GetById::new(…))` | | Java, Kotlin | `g.sys.db.gen.getByIdGen(…)` | ## Related - [Get by id API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-get-by-id-api.html) · [Generated API from code](https://docs.apimaker.dev/v4/examples/sys/db/getById.html#without-a-schema) · [The global object g](https://docs.apimaker.dev/v4/docs/pre-defined-terms/global-object-g.html) (The code of this page is also written in Python, PHP, C#, Go, Rust, Java, Kotlin : https://docs.apimaker.dev/v4/examples/sys/db/getById.md) --- # Save Single/Multiple > Insert one or more records into a collection using API Maker's g.sys.db.save method. Source: https://docs.apimaker.dev/v4/examples/sys/db/saveSingleOrMultiple.html > **The code in every language** > > Each example is the inside of `main`, written in every [language](https://docs.apimaker.dev/v4/docs/languages/index.html) API Maker runs : pick yours in the tabs, and every page shows it from then on. The types a call takes (`GetAll`, `DeepItem`…) are those of `am` : `from am import GetAll` in Python, `use am::GetAll;` in Rust, `import am.GetAll;` in Java and Kotlin ; PHP and C# have them without an import, Go names them `am.GetAll`. `g.sys.db.saveSingleOrMultiple` calls the [save single or multiple schema API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-save-single-or-multiple-api.html) of any table from your code, with the same headers and query parameters as over HTTP. It returns the data. The whole envelope (`success`, `statusCode`, `data`, `totalCount`, `errors`…) comes back when `true` is passed as the second argument in TypeScript, and through `full` in the other languages : `g.sys.db.full` (`g.Sys.Db.Full` in C# and Go, `$g->sys->db->full` in PHP). ## Save single or multiple **TypeScript** **Save single/multiple** ```typescript let saveSingleOrMultiple = await g.sys.db.saveSingleOrMultiple({ instance: "mysql_8", database: "inventory", collection: "customers", saveData: { "first_name": "Bob", "last_name": "Lin" } }); ``` ## Save single or multiple with multiple data **TypeScript** **Save single/multiple** ```typescript let saveSingleOrMultiple = await g.sys.db.saveSingleOrMultiple({ instance: "mysql_8", database: "inventory", collection: "customers", saveData: [{ "first_name": "Bob", "last_name": "Lin" }, { "first_name": "Alice", "last_name": "Page" }] }); ``` ## with header **TypeScript** **Save single/multiple with header** ```typescript let saveSingleOrMultiple = await g.sys.db.saveSingleOrMultiple({ instance: "mysql_8", database: "inventory", collection: "customers", saveData: { "first_name": "Bob", "last_name": "Lin" }, headers: { "x-am-response-case": "capitalCase", // noChange | camelCase | capitalCase | constantCase | dotCase | headerCase | noCase | paramCase | pascalCase | pathCase | sentenceCase | snakeCase }, }); ``` ## Structure **TypeScript** **Save single/multiple structure** ```typescript let saveSingleOrMultiple = await g.sys.db.saveSingleOrMultiple({ instance: "INSTANCE_NAME", database: 'DB_NAME', collection: "COLLECTION_NAME", saveData: { "COLUMN_NAME": "VALUE", "COLUMN_NAME2": "VALUE", }, headers: { "x-am-response-case": "capitalCase", // noChange | camelCase | capitalCase | constantCase | dotCase | headerCase | noCase | paramCase | pascalCase | pathCase | sentenceCase | snakeCase "x-am-response-object-type": "make_flat", // no_action | make_flat "x-am-meta": "true", // true, false "x-am-internationalization": "USER_I18N_ID", "x-am-run-in-sandbox": "2", "x-am-content-type-response": "text/xml", // application/json | text/xml | text/yaml | text/plain | text/html | application/octet-stream "x-am-cache-control": "reset_cache", // no_action | reset_cache "x-am-get-encrypted-data": "get_only_encryption", // no_encryption | get_only_encryption | get_data_and_encryption "x-am-sandbox-timeout": "13000", "x-no-compression": "true", // true | false "x-am-encrypted-payload": "true", // user will send 'true', when payload is encrypted for transfer // Multi-tenant : the tenant of the request, each instance finds it in its own tenants table "x-am-tenant-username": "TENANT_USERNAME", // ex: acme // Authorization headers "x-am-authorization": "AUTHORIZATION_TOKEN", "x-am-user-authorization": "API_USER_TOKEN", "x-aws-authorization": "AWS_TOKEN", "x-google-authorization": "GOOGLE_TOKEN", "x-azure-authorization": "AZURE_TOKEN", }, }); ``` ## Multi-tenant - `instance: "crm::acme"` works on the database of the tenant `acme` of the [multi-tenant](https://docs.apimaker.dev/v4/docs/features/multi-tenant.html) instance `crm`. - With `instance: "crm"`, the call works on the database of the tenant of the request: a custom API called with the [x-am-tenant-username](https://docs.apimaker.dev/v4/docs/apis-all/header/requestHeader.html#x-am-tenant-username) header passes it on to the APIs it calls. A request without a tenant works on the structure database. **TypeScript** **Save a customer of the tenant acme** ```typescript let saveSingleOrMultiple = await g.sys.db.saveSingleOrMultiple({ instance: "crm::acme", database: "crm", collection: "customers", saveData: { "first_name": "Bob", "last_name": "Lin" } }); ``` ## Save vectors, JSON and bytes A vector is a list of numbers, a JSON column takes any object or list, and bytes go as a `Buffer` object : a plain map in every language. They are read back in the same forms. [Data types](https://docs.apimaker.dev/v4/docs/schema/data-types.html) lists every type of every database. **TypeScript** **Save a vector, JSON and bytes** ```typescript let saved = await g.sys.db.saveSingleOrMultiple({ instance: "mysql_8", database: "inventory", collection: "products", saveData: { "name": "Mug", "embedding": [0.12, 0.5, 0.33], "details": { "color": "blue", "sizes": [250, 350] }, "photo": { "type": "Buffer", "data": [137, 80, 78, 71] } } }); ``` ## Without a schema `g.sys.db.gen.saveSingleOrMultipleGen` takes the same arguments and calls the [save single or multiple generated API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-save-single-or-multiple-api.html#without-a-schema) : no schema, so the data is read and written as it is in the table, without the conversions, validations and defaults of the schema. | Language | The call | |---|---| | TypeScript | `g.sys.db.gen.saveSingleOrMultipleGen(…)` | | Python | `g.sys.db.gen.save_single_or_multiple_gen(…)` | | PHP | `$g->sys->db->gen->saveSingleOrMultipleGen(…)` | | C#, Go | `g.Sys.Db.Gen.SaveSingleOrMultipleGen(…)` | | Rust | `g.sys.db.save_single_or_multiple_gen(Save::new(…))` | | Java, Kotlin | `g.sys.db.gen.saveSingleOrMultipleGen(…)` | ## Related - [Save single or multiple API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-save-single-or-multiple-api.html) · [Generated API from code](https://docs.apimaker.dev/v4/examples/sys/db/saveSingleOrMultiple.html#without-a-schema) · [The global object g](https://docs.apimaker.dev/v4/docs/pre-defined-terms/global-object-g.html) (The code of this page is also written in Python, PHP, C#, Go, Rust, Java, Kotlin : https://docs.apimaker.dev/v4/examples/sys/db/saveSingleOrMultiple.md) --- # Master Save/Update > Perform save or update operations on single or multiple records with master-level control using API Maker. Source: https://docs.apimaker.dev/v4/examples/sys/db/masterSave.html > **The code in every language** > > Each example is the inside of `main`, written in every [language](https://docs.apimaker.dev/v4/docs/languages/index.html) API Maker runs : pick yours in the tabs, and every page shows it from then on. The types a call takes (`GetAll`, `DeepItem`…) are those of `am` : `from am import GetAll` in Python, `use am::GetAll;` in Rust, `import am.GetAll;` in Java and Kotlin ; PHP and C# have them without an import, Go names them `am.GetAll`. `g.sys.db.masterSave` calls the [master save schema API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-master-save-api.html) of any table from your code, with the same headers and query parameters as over HTTP. It returns the data. The whole envelope (`success`, `statusCode`, `data`, `totalCount`, `errors`…) comes back when `true` is passed as the second argument in TypeScript, and through `full` in the other languages : `g.sys.db.full` (`g.Sys.Db.Full` in C# and Go, `$g->sys->db->full` in PHP). ## master save single data **TypeScript** **Master save** ```typescript let masterSave = await g.sys.db.masterSave({ instance: "mysql_8", database: "inventory", collection: "customers", saveData: { "first_name": "Bob", "last_name": "Lin" } }); ``` ## master save multiple data **TypeScript** **Master save** ```typescript let masterSave = await g.sys.db.masterSave({ instance: "mysql_8", database: "inventory", collection: "customers", saveData: [ { "first_name": "Bob", "last_name": "Lin" }, { "first_name": "Bob", "last_name": "Lin" } ] }); ``` ## with header **TypeScript** **Master save with header** ```typescript let masterSave = await g.sys.db.masterSave({ instance: "mysql_8", database: "inventory", collection: "customers", saveData: { "first_name": "Bob", "last_name": "Lin" }, headers: { "x-am-response-case": "capitalCase", // noChange | camelCase | capitalCase | constantCase | dotCase | headerCase | noCase | paramCase | pascalCase | pathCase | sentenceCase | snakeCase }, }); ``` ## multiple database entry **TypeScript** **Master save with multy data[with help of schema configuration]** ```typescript let masterSave = await g.sys.db.masterSave({ instance: "mysql_8", database: "inventory", collection: "customers", saveData: { "city_name": "Wembley", //city_name save in mysql database "state_id": { "state_name": "London", //state_name save in maria database "country_id": { "country_name":"UK" //country_name save in postGreSql database } } }, headers: { "x-am-response-case": "capitalCase", // noChange | camelCase | capitalCase | constantCase | dotCase | headerCase | noCase | paramCase | pascalCase | pathCase | sentenceCase | snakeCase }, }); ``` ## multiple database multiple entry **TypeScript** **Master save with multy data[with help of schema configuration]** ```typescript let masterSave = await g.sys.db.masterSave({ instance: "mysql_8", database: "inventory", collection: "customers", saveData: [{ "city_name": "Wembley", "state_id": { "state_name": "London", "country_id": 302 } }, { "city_name": "Buffalo", "state_id": { "state_name": "Chicago", "country_id": 303 } }], headers: { "x-am-response-case": "capitalCase", // noChange | camelCase | capitalCase | constantCase | dotCase | headerCase | noCase | paramCase | pascalCase | pathCase | sentenceCase | snakeCase }, }); ``` ## Structure **TypeScript** **Master save** ```typescript let masterSave = await g.sys.db.masterSave({ instance: "INSTANCE_NAME", database: 'DB_NAME', collection: "COLLECTION_NAME", saveData: { "COLUMN_NAME": "VALUE", "COLUMN_NAME2": "VALUE", }, headers: { "x-am-response-case": "capitalCase", // noChange | camelCase | capitalCase | constantCase | dotCase | headerCase | noCase | paramCase | pascalCase | pathCase | sentenceCase | snakeCase "x-am-response-object-type": "make_flat", // no_action | make_flat "x-am-meta": "true", // true, false "x-am-internationalization": "USER_I18N_ID", "x-am-run-in-sandbox": "2", "x-am-content-type-response": "text/xml", // application/json | text/xml | text/yaml | text/plain | text/html | application/octet-stream "x-am-cache-control": "reset_cache", // no_action | reset_cache "x-am-get-encrypted-data": "get_only_encryption", // no_encryption | get_only_encryption | get_data_and_encryption "x-am-sandbox-timeout": "13000", "x-no-compression": "true", // true | false "x-am-encrypted-payload": "true", // user will send 'true', when payload is encrypted for transfer // Multi-tenant : the tenant of the request, each instance finds it in its own tenants table "x-am-tenant-username": "TENANT_USERNAME", // ex: acme // Authorization headers "x-am-authorization": "AUTHORIZATION_TOKEN", "x-am-user-authorization": "API_USER_TOKEN", "x-aws-authorization": "AWS_TOKEN", "x-google-authorization": "GOOGLE_TOKEN", "x-azure-authorization": "AZURE_TOKEN", }, }); ``` ## Multi-tenant - `instance: "crm::acme"` works on the database of the tenant `acme` of the [multi-tenant](https://docs.apimaker.dev/v4/docs/features/multi-tenant.html) instance `crm`. - With `instance: "crm"`, the call works on the database of the tenant of the request: a custom API called with the [x-am-tenant-username](https://docs.apimaker.dev/v4/docs/apis-all/header/requestHeader.html#x-am-tenant-username) header passes it on to the APIs it calls. A request without a tenant works on the structure database. **TypeScript** **Master save a customer of the tenant acme** ```typescript let masterSave = await g.sys.db.masterSave({ instance: "crm::acme", database: "crm", collection: "customers", saveData: { "first_name": "Bob", "last_name": "Lin" } }); ``` ## Without a schema `g.sys.db.gen.masterSaveGen` takes the same arguments and calls the [master save generated API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-master-save-api.html#without-a-schema) : no schema, so the data is read and written as it is in the table, without the conversions, validations and defaults of the schema. | Language | The call | |---|---| | TypeScript | `g.sys.db.gen.masterSaveGen(…)` | | Python | `g.sys.db.gen.master_save_gen(…)` | | PHP | `$g->sys->db->gen->masterSaveGen(…)` | | C#, Go | `g.Sys.Db.Gen.MasterSaveGen(…)` | | Rust | `g.sys.db.master_save_gen(Save::new(…))` | | Java, Kotlin | `g.sys.db.gen.masterSaveGen(…)` | ## Related - [Master save API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-master-save-api.html) · [Generated API from code](https://docs.apimaker.dev/v4/examples/sys/db/masterSave.html#without-a-schema) · [The global object g](https://docs.apimaker.dev/v4/docs/pre-defined-terms/global-object-g.html) (The code of this page is also written in Python, PHP, C#, Go, Rust, Java, Kotlin : https://docs.apimaker.dev/v4/examples/sys/db/masterSave.md) --- # Array Operations > Manipulate array fields within documents using operations like push, pull, and pop in API Maker. Source: https://docs.apimaker.dev/v4/examples/sys/db/arrayOperations.html > **The code in every language** > > Each example is the inside of `main`, written in every [language](https://docs.apimaker.dev/v4/docs/languages/index.html) API Maker runs : pick yours in the tabs, and every page shows it from then on. The types a call takes (`GetAll`, `DeepItem`…) are those of `am` : `from am import GetAll` in Python, `use am::GetAll;` in Rust, `import am.GetAll;` in Java and Kotlin ; PHP and C# have them without an import, Go names them `am.GetAll`. `g.sys.db.arrayOperations` calls the [array operations schema API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-array-operations-api.html) of any table from your code, with the same headers and query parameters as over HTTP. It returns the data. The whole envelope (`success`, `statusCode`, `data`, `totalCount`, `errors`…) comes back when `true` is passed as the second argument in TypeScript, and through `full` in the other languages : `g.sys.db.full` (`g.Sys.Db.Full` in C# and Go, `$g->sys->db->full` in PHP). ## Array operation [push] **TypeScript** **Array operation push** ```typescript await g.sys.db.arrayOperations({ instance: "mongodb", database: "inventory", collection: "customers", find: { "customer_id": 1 }, operations: [ { operation: "push", path: "attributes.color", dataToPush: [ "YELLOW", "SKY_BLUE" ] } ] }); ``` ## Array operation [pull] **TypeScript** **Array operation pull** ```typescript await g.sys.db.arrayOperations({ instance: "mongodb", database: "inventory", collection: "customers", find: { "customer_id": 1 }, operations: [ { operation: "pull", path: "ages", queryToRemove: { "age": 2, "birth_year": 1989, "country_id": 1 } } ] }); ``` ## Array operation [pullAll] **TypeScript** **Array operation pullAll** ```typescript await g.sys.db.arrayOperations({ instance: "mongodb", database: "inventory", collection: "customers", find: { "customer_id": 1 }, operations: [ { operation: "pullAll", path: "attributes.size", dataToPull: [ 3.5 ] } ] }); ``` ## Array operation [pop] **TypeScript** **Array operation pop** ```typescript await g.sys.db.arrayOperations({ instance: "mongodb", database: "inventory", collection: "customers", find: { "customer_id": 1 }, operations: [ { operation: "pop", path: "attributes.color", direction: 1 } ] }); ``` ## Array operation [set] **TypeScript** **Array operation set** ```typescript await g.sys.db.arrayOperations({ instance: "mongodb", database: "inventory", collection: "customers", find: { "customer_id": 1 }, operations: [ { operation: "set", dataToSet: { 'ages.birth_year': 1890, }, arrayFilters: [ { 'item.age': 4, }, ], } ] }); ``` ## Array operation [addToSet] **TypeScript** **Array operation addToSet** ```typescript await g.sys.db.arrayOperations({ instance: "mongodb", database: "inventory", collection: "customers", find: { "customer_id": 1 }, operations: [ { operation: "addToSet", dataToSet: { 'ages.birth_year': 1890, }, arrayFilters: [ { 'item.age': 4, }, ], } ] }); ``` ## Structure **TypeScript** **Array operations** ```typescript await g.sys.db.arrayOperations({ instance: "INSTANCE_NAME", database: 'DB_NAME', collection: "COLLECTION_NAME", find: { "customer_id": 1 }, operations: [ { operation: "push", // push | addToSet | pull | pullAll | pop | set path: "attributes.color", dataToPush: [ "YELLOW", "SKY_BLUE" ] }, { operation: "pull", // push | addToSet | pull | pullAll | pop | set path: "attributes.color", dataToPull: [ "SKY_BLUE" ] } ], select: "COMMA_SEPARATED_COLUMN_NAMES", headers: { "x-am-response-case": "capitalCase", // noChange | camelCase | capitalCase | constantCase | dotCase | headerCase | noCase | paramCase | pascalCase | pathCase | sentenceCase | snakeCase "x-am-response-object-type": "make_flat", // no_action | make_flat "x-am-meta": "true", // true, false "x-am-internationalization": "USER_I18N_ID", "x-am-run-in-sandbox": "2", "x-am-content-type-response": "text/xml", // application/json | text/xml | text/yaml | text/plain | text/html | application/octet-stream "x-am-cache-control": "reset_cache", // no_action | reset_cache "x-am-get-encrypted-data": "get_only_encryption", // no_encryption | get_only_encryption | get_data_and_encryption "x-am-sandbox-timeout": "13000", "x-no-compression": "true", // true | false "x-am-encrypted-payload": "true", // user will send 'true', when payload is encrypted for transfer // Multi-tenant : the tenant of the request, each instance finds it in its own tenants table "x-am-tenant-username": "TENANT_USERNAME", // ex: acme // Authorization headers "x-am-authorization": "AUTHORIZATION_TOKEN", "x-am-user-authorization": "API_USER_TOKEN", "x-aws-authorization": "AWS_TOKEN", "x-google-authorization": "GOOGLE_TOKEN", "x-azure-authorization": "AZURE_TOKEN", }, }); ``` ## Multi-tenant - `instance: "crm::acme"` works on the database of the tenant `acme` of the [multi-tenant](https://docs.apimaker.dev/v4/docs/features/multi-tenant.html) instance `crm`. - With `instance: "crm"`, the call works on the database of the tenant of the request: a custom API called with the [x-am-tenant-username](https://docs.apimaker.dev/v4/docs/apis-all/header/requestHeader.html#x-am-tenant-username) header passes it on to the APIs it calls. A request without a tenant works on the structure database. **TypeScript** **Array operations on a customer of the tenant acme** ```typescript let arrayOperations = await g.sys.db.arrayOperations({ instance: "crm::acme", database: "crm", collection: "customers", find: { "customer_id": 1 }, operations: [ { operation: "push", path: "tags", dataToPush: ["vip"] } ] }); ``` ## Without a schema `g.sys.db.gen.arrayOperationsGen` takes the same arguments and calls the [array operations generated API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-array-operations-api.html#without-a-schema) : no schema, so the data is read and written as it is in the table, without the conversions, validations and defaults of the schema. | Language | The call | |---|---| | TypeScript | `g.sys.db.gen.arrayOperationsGen(…)` | | Python | `g.sys.db.gen.array_operations_gen(…)` | | PHP | `$g->sys->db->gen->arrayOperationsGen(…)` | | C#, Go | `g.Sys.Db.Gen.ArrayOperationsGen(…)` | | Rust | `g.sys.db.array_operations_gen(ArrayOperations::new(…))` | | Java, Kotlin | `g.sys.db.gen.arrayOperationsGen(…)` | ## Related - [Array operations API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-array-operations-api.html) · [Generated API from code](https://docs.apimaker.dev/v4/examples/sys/db/arrayOperations.html#without-a-schema) · [The global object g](https://docs.apimaker.dev/v4/docs/pre-defined-terms/global-object-g.html) (The code of this page is also written in Python, PHP, C#, Go, Rust, Java, Kotlin : https://docs.apimaker.dev/v4/examples/sys/db/arrayOperations.md) --- # Update by ID > Update a single record in a collection based on its unique identifier using API Maker's g.sys.db.updateById method. Source: https://docs.apimaker.dev/v4/examples/sys/db/updateById.html > **The code in every language** > > Each example is the inside of `main`, written in every [language](https://docs.apimaker.dev/v4/docs/languages/index.html) API Maker runs : pick yours in the tabs, and every page shows it from then on. The types a call takes (`GetAll`, `DeepItem`…) are those of `am` : `from am import GetAll` in Python, `use am::GetAll;` in Rust, `import am.GetAll;` in Java and Kotlin ; PHP and C# have them without an import, Go names them `am.GetAll`. `g.sys.db.updateById` calls the [update by id schema API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-update-by-id-api.html) of any table from your code, with the same headers and query parameters as over HTTP. It returns the data. The whole envelope (`success`, `statusCode`, `data`, `totalCount`, `errors`…) comes back when `true` is passed as the second argument in TypeScript, and through `full` in the other languages : `g.sys.db.full` (`g.Sys.Db.Full` in C# and Go, `$g->sys->db->full` in PHP). ## Update by id **TypeScript** **Update By Id** ```typescript let updateById = await g.sys.db.updateById({ instance: "mysql_8", database: "inventory", collection: "customers", id: 1, updateData: { "first_name": "MALLORY" } }); ``` ## Update by id primaryKey override **TypeScript** **Update By Id primarykey override** ```typescript let updateById = await g.sys.db.updateById({ instance: "mysql_8", database: "inventory", collection: "customers", id: "Alice", primaryKey: "first_name", updateData: { "first_name": "MALLORY" } }); ``` ## Update by id [upsert] **TypeScript** **Update By Id with upsert** ```typescript let updateById = await g.sys.db.updateById({ instance: "mysql_8", database: "inventory", collection: "customers", id: "202", updateData: { "first_name": "MALLORY", "last_name": "ANI" }, upsert: true }); ``` ## Update by id [returnDocument] **TypeScript** **Update By Id with returnDocument** ```typescript let updateById = await g.sys.db.updateById({ instance: "mysql_8", database: "inventory", collection: "customers", id: "202", updateData: { "first_name": "MALLORY" }, returnDocument: 'before', // return old doc if value 'before'. Supported values are 'before' | 'after'. }); ``` ## Structure **TypeScript** **Update by id with all params** ```typescript let updateById = await g.sys.db.updateById({ instance: "INSTANCE_NAME", database: 'DB_NAME', collection: "COLLECTION_NAME", id: 1008, primaryKey: "id", updateData: { "first_name": "Tanmay", }, returnDocument: 'before', // return old doc if value 'before'. Supported values are 'before' | 'after'. select: "COLUMN_NAMES", upsert: false, headers: { "x-am-response-case": "capitalCase", // noChange | camelCase | capitalCase | constantCase | dotCase | headerCase | noCase | paramCase | pascalCase | pathCase | sentenceCase | snakeCase "x-am-response-object-type": "make_flat", // no_action | make_flat "x-am-meta": "true", // true, false "x-am-internationalization": "USER_I18N_ID", "x-am-run-in-sandbox": "2", "x-am-content-type-response": "text/xml", // application/json | text/xml | text/yaml | text/plain | text/html | application/octet-stream "x-am-cache-control": "reset_cache", // no_action | reset_cache "x-am-get-encrypted-data": "get_only_encryption", // no_encryption | get_only_encryption | get_data_and_encryption "x-am-sandbox-timeout": "13000", "x-no-compression": "true", // true | false "x-am-encrypted-payload": "true", // user will send 'true', when payload is encrypted for transfer // Multi-tenant : the tenant of the request, each instance finds it in its own tenants table "x-am-tenant-username": "TENANT_USERNAME", // ex: acme // Authorization headers "x-am-authorization": "AUTHORIZATION_TOKEN", "x-am-user-authorization": "API_USER_TOKEN", "x-aws-authorization": "AWS_TOKEN", "x-google-authorization": "GOOGLE_TOKEN", "x-azure-authorization": "AZURE_TOKEN", }, }); ``` ## Multi-tenant - `instance: "crm::acme"` works on the database of the tenant `acme` of the [multi-tenant](https://docs.apimaker.dev/v4/docs/features/multi-tenant.html) instance `crm`. - With `instance: "crm"`, the call works on the database of the tenant of the request: a custom API called with the [x-am-tenant-username](https://docs.apimaker.dev/v4/docs/apis-all/header/requestHeader.html#x-am-tenant-username) header passes it on to the APIs it calls. A request without a tenant works on the structure database. **TypeScript** **Update the customer 1 of the tenant acme** ```typescript let updateById = await g.sys.db.updateById({ instance: "crm::acme", database: "crm", collection: "customers", id: 1, updateData: { "first_name": "MALLORY" } }); ``` ## Without a schema `g.sys.db.gen.updateByIdGen` takes the same arguments and calls the [update by id generated API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-update-by-id-api.html#without-a-schema) : no schema, so the data is read and written as it is in the table, without the conversions, validations and defaults of the schema. | Language | The call | |---|---| | TypeScript | `g.sys.db.gen.updateByIdGen(…)` | | Python | `g.sys.db.gen.update_by_id_gen(…)` | | PHP | `$g->sys->db->gen->updateByIdGen(…)` | | C#, Go | `g.Sys.Db.Gen.UpdateByIdGen(…)` | | Rust | `g.sys.db.update_by_id_gen(UpdateById::new(…))` | | Java, Kotlin | `g.sys.db.gen.updateByIdGen(…)` | ## Related - [Update by id API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-update-by-id-api.html) · [Generated API from code](https://docs.apimaker.dev/v4/examples/sys/db/updateById.html#without-a-schema) · [The global object g](https://docs.apimaker.dev/v4/docs/pre-defined-terms/global-object-g.html) (The code of this page is also written in Python, PHP, C#, Go, Rust, Java, Kotlin : https://docs.apimaker.dev/v4/examples/sys/db/updateById.md) --- # Update Many > Update multiple records in a collection based on specified criteria using API Maker's g.sys.db.updateMany method. Source: https://docs.apimaker.dev/v4/examples/sys/db/updateMany.html > **The code in every language** > > Each example is the inside of `main`, written in every [language](https://docs.apimaker.dev/v4/docs/languages/index.html) API Maker runs : pick yours in the tabs, and every page shows it from then on. The types a call takes (`GetAll`, `DeepItem`…) are those of `am` : `from am import GetAll` in Python, `use am::GetAll;` in Rust, `import am.GetAll;` in Java and Kotlin ; PHP and C# have them without an import, Go names them `am.GetAll`. `g.sys.db.updateMany` calls the [update many schema API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-update-many-api.html) of any table from your code, with the same headers and query parameters as over HTTP. It returns the data. The whole envelope (`success`, `statusCode`, `data`, `totalCount`, `errors`…) comes back when `true` is passed as the second argument in TypeScript, and through `full` in the other languages : `g.sys.db.full` (`g.Sys.Db.Full` in C# and Go, `$g->sys->db->full` in PHP). ## Simple update-many **TypeScript** **Update many** ```typescript let updateMany = await g.sys.db.updateMany({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "first_name": "Alice" }, updateData: { "first_name": "MALLORY" } }); ``` ## update-many with header **TypeScript** **Update many with header** ```typescript let updateMany = await g.sys.db.updateMany({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "first_name": "Alice" }, updateData: { "first_name": "MALLORY" }, headers: { "x-am-response-case": "capitalCase", // noChange | camelCase | capitalCase | constantCase | dotCase | headerCase | noCase | paramCase | pascalCase | pathCase | sentenceCase | snakeCase }, }); ``` ## $in update-many **TypeScript** **$in Update many** ```typescript let updateMany = await g.sys.db.updateMany({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "customer_id": { "$in": [2, 3] } }, updateData: { "first_name": "MALLORY" } }); ``` ## $nin update-many **TypeScript** **$nin Update many** ```typescript let updateMany = await g.sys.db.updateMany({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "customer_id": { "$nin": [2, 3] } }, updateData: { "first_name": "MALLORY" } }); ``` ## $and update-many **TypeScript** **$and Update many** ```typescript let updateMany = await g.sys.db.updateMany({ instance: "mysql_8", database: "inventory", collection: "customers", find: { $and: [ { "first_name": "Alice" }, { "isActive": 1 } ] }, updateData: { "first_name": "MALLORY" } }); ``` ## $or update-many **TypeScript** **$or Update many** ```typescript let updateMany = await g.sys.db.updateMany({ instance: "mysql_8", database: "inventory", collection: "customers", find: { $or: [ { "first_name": "Alice" }, { "isActive": 1 } ] }, updateData: { "first_name": "MALLORY" } }); ``` ## $eq update-many **TypeScript** **$eq Update many** ```typescript let updateMany = await g.sys.db.updateMany({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "customer_id": { "$eq": 2 } }, updateData: { "first_name": "MALLORY" } }); ``` ## $gt update-many **TypeScript** **$gt Update many** ```typescript let updateMany = await g.sys.db.updateMany({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "customer_id": { "$gt": 2 } }, updateData: { "first_name": "MALLORY" } }); ``` ## $gte update-many **TypeScript** **$gte Update many** ```typescript let updateMany = await g.sys.db.updateMany({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "customer_id": { "$gte": 2 } }, updateData: { "first_name": "MALLORY" } }); ``` ## $lt update-many **TypeScript** **$lt Update many** ```typescript let updateMany = await g.sys.db.updateMany({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "customer_id": { "$lt": 2 } }, updateData: { "first_name": "MALLORY" } }); ``` ## $lte update-many **TypeScript** **$lte Update many** ```typescript let updateMany = await g.sys.db.updateMany({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "customer_id": { "$lte": 2 } }, updateData: { "first_name": "MALLORY" } }); ``` ## [mongoDB] update-many **TypeScript** **$mongoDB Update many** ```typescript let updateMany = await g.sys.db.updateMany({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "customer_id": 2, "ages.birth_year": "1889" }, updateData: { "ages.$.age": "35" } }); ``` ## [MongoDB] $elemMatch, $gte, $lte update-many **TypeScript** **$elemMatch, $gte, $lte Update many** ```typescript let updateMany = await g.sys.db.updateMany({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "customer_id": 2, "ages": { "$elemMatch": { "age": { "$gte": 30 }, "birth_year": { "$lte": 1900 } } } }, updateData: { "first_name": "MALLORY" } }); ``` ## Structure **TypeScript** **Update many** ```typescript let updateMany = await g.sys.db.updateMany({ instance: "INSTANCE_NAME", database: 'DB_NAME', collection: "COLLECTION_NAME", find: { "COLUMN_NAME": "VALUE", }, updateData: { "COLUMN_NAME": "VALUE", }, headers: { "x-am-response-case": "capitalCase", // noChange | camelCase | capitalCase | constantCase | dotCase | headerCase | noCase | paramCase | pascalCase | pathCase | sentenceCase | snakeCase "x-am-response-object-type": "make_flat", // no_action | make_flat "x-am-meta": "true", // true, false "x-am-internationalization": "USER_I18N_ID", "x-am-run-in-sandbox": "2", "x-am-content-type-response": "text/xml", // application/json | text/xml | text/yaml | text/plain | text/html | application/octet-stream "x-am-cache-control": "reset_cache", // no_action | reset_cache "x-am-get-encrypted-data": "get_only_encryption", // no_encryption | get_only_encryption | get_data_and_encryption "x-am-sandbox-timeout": "13000", "x-no-compression": "true", // true | false "x-am-encrypted-payload": "true", // user will send 'true', when payload is encrypted for transfer // Multi-tenant : the tenant of the request, each instance finds it in its own tenants table "x-am-tenant-username": "TENANT_USERNAME", // ex: acme // Authorization headers "x-am-authorization": "AUTHORIZATION_TOKEN", "x-am-user-authorization": "API_USER_TOKEN", "x-aws-authorization": "AWS_TOKEN", "x-google-authorization": "GOOGLE_TOKEN", "x-azure-authorization": "AZURE_TOKEN", }, }); ``` ## Multi-tenant - `instance: "crm::acme"` works on the database of the tenant `acme` of the [multi-tenant](https://docs.apimaker.dev/v4/docs/features/multi-tenant.html) instance `crm`. - With `instance: "crm"`, the call works on the database of the tenant of the request: a custom API called with the [x-am-tenant-username](https://docs.apimaker.dev/v4/docs/apis-all/header/requestHeader.html#x-am-tenant-username) header passes it on to the APIs it calls. A request without a tenant works on the structure database. **TypeScript** **Update many customers of the tenant acme** ```typescript let updateMany = await g.sys.db.updateMany({ instance: "crm::acme", database: "crm", collection: "customers", find: { "first_name": "Alice" }, updateData: { "first_name": "MALLORY" } }); ``` ## Without a schema `g.sys.db.gen.updateManyGen` takes the same arguments and calls the [update many generated API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-update-many-api.html#without-a-schema) : no schema, so the data is read and written as it is in the table, without the conversions, validations and defaults of the schema. | Language | The call | |---|---| | TypeScript | `g.sys.db.gen.updateManyGen(…)` | | Python | `g.sys.db.gen.update_many_gen(…)` | | PHP | `$g->sys->db->gen->updateManyGen(…)` | | C#, Go | `g.Sys.Db.Gen.UpdateManyGen(…)` | | Rust | `g.sys.db.update_many_gen(UpdateMany::new(…))` | | Java, Kotlin | `g.sys.db.gen.updateManyGen(…)` | ## Related - [Update many API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-update-many-api.html) · [Generated API from code](https://docs.apimaker.dev/v4/examples/sys/db/updateMany.html#without-a-schema) · [The global object g](https://docs.apimaker.dev/v4/docs/pre-defined-terms/global-object-g.html) (The code of this page is also written in Python, PHP, C#, Go, Rust, Java, Kotlin : https://docs.apimaker.dev/v4/examples/sys/db/updateMany.md) --- # Replace by ID > Replace a record in a collection with a new document based on its unique identifier using API Maker's g.sys.db.replaceById method. Source: https://docs.apimaker.dev/v4/examples/sys/db/replaceById.html > **The code in every language** > > Each example is the inside of `main`, written in every [language](https://docs.apimaker.dev/v4/docs/languages/index.html) API Maker runs : pick yours in the tabs, and every page shows it from then on. The types a call takes (`GetAll`, `DeepItem`…) are those of `am` : `from am import GetAll` in Python, `use am::GetAll;` in Rust, `import am.GetAll;` in Java and Kotlin ; PHP and C# have them without an import, Go names them `am.GetAll`. `g.sys.db.replaceById` calls the [replace by id schema API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-replace-by-id-api.html) of any table from your code, with the same headers and query parameters as over HTTP. It returns the data. The whole envelope (`success`, `statusCode`, `data`, `totalCount`, `errors`…) comes back when `true` is passed as the second argument in TypeScript, and through `full` in the other languages : `g.sys.db.full` (`g.Sys.Db.Full` in C# and Go, `$g->sys->db->full` in PHP). ## Replace By Id **TypeScript** **Replace By Id** ```typescript let replaceById = await g.sys.db.replaceById({ instance: "mysql_8", database: "inventory", collection: "customers", id: 1, updateData: { "first_name": "MALLORY" } }); ``` ## Replace By Id [primaryKey] override **TypeScript** **Replace By Id primary key override** ```typescript let replaceById = await g.sys.db.replaceById({ instance: "mysql_8", database: "inventory", collection: "customers", id: "Bob", primaryKey: "first_name", updateData: { "first_name": "MALLORY" } }); ``` ## Replace By Id [header] **TypeScript** **Replace By Id header** ```typescript let replaceById = await g.sys.db.replaceById({ instance: "mysql_8", database: "inventory", collection: "customers", id: 606, updateData: { "first_name": "MALLORY" }, headers: { "x-am-response-case": "capitalCase", // noChange | camelCase | capitalCase | constantCase | dotCase | headerCase | noCase | paramCase | pascalCase | pathCase | sentenceCase | snakeCase }, }); ``` ## Replace By Id [upsert] **TypeScript** **Replace By Id upsert** ```typescript let replaceById = await g.sys.db.replaceById({ instance: "mysql_8", database: "inventory", collection: "customers", id: 505, updateData: { "first_name": "MALLORY" }, upsert: true }); ``` ## Replace By Id [returnDocument] **TypeScript** **Replace By Id returnDocument** ```typescript let replaceById = await g.sys.db.replaceById({ instance: "mysql_8", database: "inventory", collection: "customers", id: 80, updateData: { "first_name": "MALLORY" }, returnDocument: 'before', // return old doc if value 'before'. Supported values are 'before' | 'after'. }); ``` ## Structure **TypeScript** **Replace by id with all params** ```typescript let replaceById = await g.sys.db.replaceById({ instance: "mysql_8", database: "inventory", collection: "customers", id: 45855, primaryKey: "pincode", updateData: { "first_name": "Elonn", "last_name": "Mask" }, returnDocument: 'before', // return old doc if value 'before'. Supported values are 'before' | 'after'. select: "COMMA_SEPARATED_COLUMN_NAMES", upsert: false, headers: { "x-am-response-case": "capitalCase", // noChange | camelCase | capitalCase | constantCase | dotCase | headerCase | noCase | paramCase | pascalCase | pathCase | sentenceCase | snakeCase "x-am-response-object-type": "make_flat", // no_action | make_flat "x-am-meta": "true", // true, false "x-am-internationalization": "USER_I18N_ID", "x-am-run-in-sandbox": "2", "x-am-content-type-response": "text/xml", // application/json | text/xml | text/yaml | text/plain | text/html | application/octet-stream "x-am-cache-control": "reset_cache", // no_action | reset_cache "x-am-get-encrypted-data": "get_only_encryption", // no_encryption | get_only_encryption | get_data_and_encryption "x-am-sandbox-timeout": "13000", "x-no-compression": "true", // true | false "x-am-encrypted-payload": "true", // user will send 'true', when payload is encrypted for transfer // Multi-tenant : the tenant of the request, each instance finds it in its own tenants table "x-am-tenant-username": "TENANT_USERNAME", // ex: acme // Authorization headers "x-am-authorization": "AUTHORIZATION_TOKEN", "x-am-user-authorization": "API_USER_TOKEN", "x-aws-authorization": "AWS_TOKEN", "x-google-authorization": "GOOGLE_TOKEN", "x-azure-authorization": "AZURE_TOKEN", }, }); ``` ## Multi-tenant - `instance: "crm::acme"` works on the database of the tenant `acme` of the [multi-tenant](https://docs.apimaker.dev/v4/docs/features/multi-tenant.html) instance `crm`. - With `instance: "crm"`, the call works on the database of the tenant of the request: a custom API called with the [x-am-tenant-username](https://docs.apimaker.dev/v4/docs/apis-all/header/requestHeader.html#x-am-tenant-username) header passes it on to the APIs it calls. A request without a tenant works on the structure database. **TypeScript** **Replace the customer 1 of the tenant acme** ```typescript let replaceById = await g.sys.db.replaceById({ instance: "crm::acme", database: "crm", collection: "customers", id: 1, updateData: { "first_name": "MALLORY", "last_name": "Lin" } }); ``` ## Without a schema `g.sys.db.gen.replaceByIdGen` takes the same arguments and calls the [replace by id generated API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-replace-by-id-api.html#without-a-schema) : no schema, so the data is read and written as it is in the table, without the conversions, validations and defaults of the schema. | Language | The call | |---|---| | TypeScript | `g.sys.db.gen.replaceByIdGen(…)` | | Python | `g.sys.db.gen.replace_by_id_gen(…)` | | PHP | `$g->sys->db->gen->replaceByIdGen(…)` | | C#, Go | `g.Sys.Db.Gen.ReplaceByIdGen(…)` | | Rust | `g.sys.db.replace_by_id_gen(UpdateById::new(…))` | | Java, Kotlin | `g.sys.db.gen.replaceByIdGen(…)` | ## Related - [Replace by id API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-replace-by-id-api.html) · [Generated API from code](https://docs.apimaker.dev/v4/examples/sys/db/replaceById.html#without-a-schema) · [The global object g](https://docs.apimaker.dev/v4/docs/pre-defined-terms/global-object-g.html) (The code of this page is also written in Python, PHP, C#, Go, Rust, Java, Kotlin : https://docs.apimaker.dev/v4/examples/sys/db/replaceById.md) --- # Remove by ID > Delete a single record from a collection based on its unique identifier using API Maker's g.sys.db.removeById method. Source: https://docs.apimaker.dev/v4/examples/sys/db/removeById.html > **The code in every language** > > Each example is the inside of `main`, written in every [language](https://docs.apimaker.dev/v4/docs/languages/index.html) API Maker runs : pick yours in the tabs, and every page shows it from then on. The types a call takes (`GetAll`, `DeepItem`…) are those of `am` : `from am import GetAll` in Python, `use am::GetAll;` in Rust, `import am.GetAll;` in Java and Kotlin ; PHP and C# have them without an import, Go names them `am.GetAll`. `g.sys.db.removeById` calls the [remove by id schema API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-remove-by-id-api.html) of any table from your code, with the same headers and query parameters as over HTTP. It returns the data. The whole envelope (`success`, `statusCode`, `data`, `totalCount`, `errors`…) comes back when `true` is passed as the second argument in TypeScript, and through `full` in the other languages : `g.sys.db.full` (`g.Sys.Db.Full` in C# and Go, `$g->sys->db->full` in PHP). ## Remove By Id **TypeScript** **Remove By Id** ```typescript let removeById = await g.sys.db.removeById({ instance: "mysql_8", database: "inventory", collection: "customers", id: 101 }); ``` ## Remove By Id [primaryKey] override **TypeScript** **Remove By Id primary key override** ```typescript let removeById = await g.sys.db.removeById({ instance: "mysql_8", database: "inventory", collection: "customers", id: "Bob", primaryKey: "first_name" }); ``` ## removeById [header] **TypeScript** **Remove By Id header** ```typescript let removeById = await g.sys.db.removeById({ instance: "mysql_8", database: "inventory", collection: "customers", id: "Bob", primaryKey: "first_name", headers: { "x-am-response-case": "capitalCase", // noChange | camelCase | capitalCase | constantCase | dotCase | headerCase | noCase | paramCase | pascalCase | pathCase | sentenceCase | snakeCase }, }); ``` ## Structure **TypeScript** **Remove by id with all params** ```typescript let removeById = await g.sys.db.removeById({ instance: "INSTANCE_NAME", database: 'DB_NAME', collection: "COLLECTION_NAME", id: 7878, primaryKey: "COLUMN_NAME", select: "COMMA_SEPARATED_COLUMN_NAMES", headers: { "x-am-response-case": "capitalCase", // noChange | camelCase | capitalCase | constantCase | dotCase | headerCase | noCase | paramCase | pascalCase | pathCase | sentenceCase | snakeCase "x-am-response-object-type": "make_flat", // no_action | make_flat "x-am-meta": "true", // true, false "x-am-internationalization": "USER_I18N_ID", "x-am-run-in-sandbox": "2", "x-am-content-type-response": "text/xml", // application/json | text/xml | text/yaml | text/plain | text/html | application/octet-stream "x-am-cache-control": "reset_cache", // no_action | reset_cache "x-am-get-encrypted-data": "get_only_encryption", // no_encryption | get_only_encryption | get_data_and_encryption "x-am-sandbox-timeout": "13000", "x-no-compression": "true", // true | false "x-am-encrypted-payload": "true", // user will send 'true', when payload is encrypted for transfer // Multi-tenant : the tenant of the request, each instance finds it in its own tenants table "x-am-tenant-username": "TENANT_USERNAME", // ex: acme // Authorization headers "x-am-authorization": "AUTHORIZATION_TOKEN", "x-am-user-authorization": "API_USER_TOKEN", "x-aws-authorization": "AWS_TOKEN", "x-google-authorization": "GOOGLE_TOKEN", "x-azure-authorization": "AZURE_TOKEN", }, }); ``` ## Multi-tenant - `instance: "crm::acme"` works on the database of the tenant `acme` of the [multi-tenant](https://docs.apimaker.dev/v4/docs/features/multi-tenant.html) instance `crm`. - With `instance: "crm"`, the call works on the database of the tenant of the request: a custom API called with the [x-am-tenant-username](https://docs.apimaker.dev/v4/docs/apis-all/header/requestHeader.html#x-am-tenant-username) header passes it on to the APIs it calls. A request without a tenant works on the structure database. **TypeScript** **Remove the customer 101 of the tenant acme** ```typescript let removeById = await g.sys.db.removeById({ instance: "crm::acme", database: "crm", collection: "customers", id: 101 }); ``` ## Without a schema `g.sys.db.gen.removeByIdGen` takes the same arguments and calls the [remove by id generated API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-remove-by-id-api.html#without-a-schema) : no schema, so the data is read and written as it is in the table, without the conversions, validations and defaults of the schema. | Language | The call | |---|---| | TypeScript | `g.sys.db.gen.removeByIdGen(…)` | | Python | `g.sys.db.gen.remove_by_id_gen(…)` | | PHP | `$g->sys->db->gen->removeByIdGen(…)` | | C#, Go | `g.Sys.Db.Gen.RemoveByIdGen(…)` | | Rust | `g.sys.db.remove_by_id_gen(RemoveById::new(…))` | | Java, Kotlin | `g.sys.db.gen.removeByIdGen(…)` | ## Related - [Remove by id API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-remove-by-id-api.html) · [Generated API from code](https://docs.apimaker.dev/v4/examples/sys/db/removeById.html#without-a-schema) · [The global object g](https://docs.apimaker.dev/v4/docs/pre-defined-terms/global-object-g.html) (The code of this page is also written in Python, PHP, C#, Go, Rust, Java, Kotlin : https://docs.apimaker.dev/v4/examples/sys/db/removeById.md) --- # Query for Get Data > Perform complex queries to retrieve data from a collection with filtering, sorting, and pagination using API Maker. Source: https://docs.apimaker.dev/v4/examples/sys/db/query.html > **The code in every language** > > Each example is the inside of `main`, written in every [language](https://docs.apimaker.dev/v4/docs/languages/index.html) API Maker runs : pick yours in the tabs, and every page shows it from then on. The types a call takes (`GetAll`, `DeepItem`…) are those of `am` : `from am import GetAll` in Python, `use am::GetAll;` in Rust, `import am.GetAll;` in Java and Kotlin ; PHP and C# have them without an import, Go names them `am.GetAll`. ## Simple query **TypeScript** **Simple query to get data** ```typescript let query = await g.sys.db.query({ instance: "mysql_8", database: "inventory", collection: "customers", find:{ "first_name": "Bob" }, }); ``` ## query [headers] **TypeScript** **query headers** ```typescript let query = await g.sys.db.query({ instance: "mysql_8", database: "inventory", collection: "customers", find:{ "first_name": "Bob" }, headers: { "x-am-response-case": "capitalCase", // noChange | camelCase | capitalCase | constantCase | dotCase | headerCase | noCase | paramCase | pascalCase | pathCase | sentenceCase | snakeCase }, }); ``` ## query [select] **TypeScript** **query select** ```typescript let query = await g.sys.db.query({ instance: "mysql_8", database: "inventory", collection: "customers", find:{ "first_name": "Bob" }, select: "first_name" }); ``` ## query [limit] **TypeScript** **query limit** ```typescript let query = await g.sys.db.query({ instance: "mysql_8", database: "inventory", collection: "customers", find:{ "first_name": "Bob" }, limit: 2 }); ``` ## query [skip] **TypeScript** **query skip** ```typescript let query = await g.sys.db.query({ instance: "mysql_8", database: "inventory", collection: "customers", find:{ "first_name": "Bob" }, skip: 1 }); ``` ## query [sort] **TypeScript** **query sort** ```typescript let query = await g.sys.db.query({ instance: "mysql_8", database: "inventory", collection: "customers", find:{ "first_name": "Bob" }, sort: "first_name" }); ``` ## query [deep] **TypeScript** **query deep** ```typescript let query = await g.sys.db.query({ instance: "mysql_8", database: "inventory", collection: "customers", find:{ "first_name": "Bob" }, deep: [ { s_key: "customer_id", t_instance: "mysql", t_db: "inventory", t_col: "products", t_key: "owner_id", } ], }); ``` ## $lt [less than] query **TypeScript** **less than query** ```typescript let query = await g.sys.db.query({ instance: "mysql_8", database: "inventory", collection: "customers", find: { customer_id: { "$lt": 2 } } }); ``` ## $lte [less than equal] query **TypeScript** **less than equal query** ```typescript let query = await g.sys.db.query({ instance: "mysql_8", database: "inventory", collection: "customers", find: { customer_id: { "$lte": 2 } } }); ``` ## $gt [greater than] query **TypeScript** **greater than query** ```typescript let query = await g.sys.db.query({ instance: "mysql_8", database: "inventory", collection: "customers", find: { customer_id: { "$gt": 2 } } }); ``` ## $gte [greater than equal] query **TypeScript** **greater than equal query** ```typescript let query = await g.sys.db.query({ instance: "mysql_8", database: "inventory", collection: "customers", find: { customer_id: { "$gte": 2 } } }); ``` ## $eq [equal to] query **TypeScript** **$eq query** ```typescript let query = await g.sys.db.query({ instance: "mysql_8", database: "inventory", collection: "customers", find: { customer_id: { "$eq": 2 } } }); ``` ## $ne [not equal to] query **TypeScript** **$ne query** ```typescript let query = await g.sys.db.query({ instance: "mysql_8", database: "inventory", collection: "customers", find: { customer_id: { "$ne": 2 } } }); ``` ## $not [not] query **TypeScript** **$not query** ```typescript let query = await g.sys.db.query({ instance: "mysql_8", database: "inventory", collection: "customers", find: { customer_id: { "$not": { "$in": [1, 2, 3, 4] } } } }); ``` ## $and [and] query **TypeScript** **$and query** ```typescript let query = await g.sys.db.query({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "$and": [ { "customer_id": 2 }, { "pincode": 7171 } ] } }); ``` Find-join example **TypeScript** **find join $and query** ```typescript let query = await g.sys.db.query({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "$and": [ { "first_name.customer_id.shipping_id": 2 }, { "first_name.customer_id.order_id": 58 } ] } }); ``` ## $or [or] query **TypeScript** **$or query** ```typescript let query = await g.sys.db.query({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "$or": [ { "customer_id": 2 }, { "pincode": 7171 } ] } }); ``` Find-join example **TypeScript** **find join $or query** ```typescript let query = await g.sys.db.query({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "$or": [ { "first_name.customer_id.shipping_id": 2 }, { "first_name.customer_id.order_id": 58 } ] } }); ``` ## $in [in] query **TypeScript** **$in query** ```typescript let query = await g.sys.db.query({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "customer_id": { "$in": [1, 2] } } }); ``` ## $nin [not in] query **TypeScript** **$nin query** ```typescript let query = await g.sys.db.query({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "customer_id": { "$nin": [1, 2] } } }); ``` ## $like [like] query **TypeScript** **$like query** ```typescript let query = await g.sys.db.query({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "first_name": { "$like": "Bob%" } } }); ``` ## $isNull [null check] with sql databases **TypeScript** **$isNull use** ```typescript let query = await g.sys.db.query({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "first_name": { "$isNull": true } } }); ``` ## MongoDB $in operator in nested find **TypeScript** **$in operator in nested find** ```typescript let query = await g.sys.db.query({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "eventListeners.versions.name": { "$in": [ "Original", "1" ] } } }); ``` ## MongoDB $nin operator in nested find **TypeScript** **$nin operator in nested find** ```typescript let query = await g.sys.db.query({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "eventListeners.versions.name": { "$nin": [ "Original", "1" ] } } }); ``` ## MongoDB $and operator in nested find **TypeScript** **$and operator in nested find** ```typescript let query = await g.sys.db.query({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "$and": [ { "eventListeners.versions.name": "Original" }, { "eventListeners.versions.version": "-1" } ] } }); ``` ## MongoDB $or operator in nested find **TypeScript** **$or operator in nested find** ```typescript let query = await g.sys.db.query({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "$or": [ { "eventListeners.versions.name": "Original" }, { "eventListeners.versions.version": "-1" } ] } }); ``` ## Structure **TypeScript** **query with all params ** ```typescript let query = await g.sys.db.query({ instance: "INSTANCE_NAME", database: 'DB_NAME', collection: "COLLECTION_NAME", find: { "COLUMN_NAME": "VALUE" }, limit: 10, select: "COMMA_SEPARATED_COLUMN_NAMES", deep: [ { s_key: "SOURCE_COLLECTION_COLUMN_NAME", t_instance: "TARGET_INSTANCE_NAME", t_db: "TARGET_DATABASE_NAME", t_col: "TARGET_COLLECTION_NAME", t_key: "TARGET_COLLECTION_COLUMN_NAME", find: { "COLUMN_NAME": "COLUMN_VALUE" }, isMultiple: true, limit: 10, select: "COMMA_SEPARATED_COLUMN_NAMES", skip: 2, sort: "COLUMN_NAME", } ], skip: 1, sort: "COLUMN_NAME", groupBy: "COLUMN_NAME", getTotalCount: true, headers: { "x-am-response-case": "capitalCase", // noChange | camelCase | capitalCase | constantCase | dotCase | headerCase | noCase | paramCase | pascalCase | pathCase | sentenceCase | snakeCase "x-am-response-object-type": "make_flat", // no_action | make_flat "x-am-meta": "true", // true, false "x-am-internationalization": "USER_I18N_ID", "x-am-run-in-sandbox": "2", "x-am-content-type-response": "text/xml", // application/json | text/xml | text/yaml | text/plain | text/html | application/octet-stream "x-am-cache-control": "reset_cache", // no_action | reset_cache "x-am-get-encrypted-data": "get_only_encryption", // no_encryption | get_only_encryption | get_data_and_encryption "x-am-sandbox-timeout": "13000", "x-no-compression": "true", // true | false "x-am-encrypted-payload": "true", // user will send 'true', when payload is encrypted for transfer // Multi-tenant : the tenant of the request, each instance finds it in its own tenants table "x-am-tenant-username": "TENANT_USERNAME", // ex: acme // Authorization headers "x-am-authorization": "AUTHORIZATION_TOKEN", "x-am-user-authorization": "API_USER_TOKEN", "x-aws-authorization": "AWS_TOKEN", "x-google-authorization": "GOOGLE_TOKEN", "x-azure-authorization": "AZURE_TOKEN", }, }, true); ``` ## Multi-tenant - `instance: "crm::acme"` works on the database of the tenant `acme` of the [multi-tenant](https://docs.apimaker.dev/v4/docs/features/multi-tenant.html) instance `crm`. - With `instance: "crm"`, the call works on the database of the tenant of the request: a custom API called with the [x-am-tenant-username](https://docs.apimaker.dev/v4/docs/apis-all/header/requestHeader.html#x-am-tenant-username) header passes it on to the APIs it calls. A request without a tenant works on the structure database. **TypeScript** **Query the customers of the tenant acme** ```typescript let query = await g.sys.db.query({ instance: "crm::acme", database: "crm", collection: "customers", find: { "first_name": "Bob" }, sort: "customer_id", limit: 10 }); ``` ## Without a schema `g.sys.db.gen.queryGen` takes the same arguments and calls the [query for get data generated API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-query-for-get-data-api.html#without-a-schema) : no schema, so the data is read and written as it is in the table, without the conversions, validations and defaults of the schema. | Language | The call | |---|---| | TypeScript | `g.sys.db.gen.queryGen(…)` | | Python | `g.sys.db.gen.query_gen(…)` | | PHP | `$g->sys->db->gen->queryGen(…)` | | C#, Go | `g.Sys.Db.Gen.QueryGen(…)` | | Rust | `g.sys.db.query_gen(Query::new(…))` | | Java, Kotlin | `g.sys.db.gen.queryGen(…)` | (The code of this page is also written in Python, PHP, C#, Go, Rust, Java, Kotlin : https://docs.apimaker.dev/v4/examples/sys/db/query.md) --- # Query for Get Data by Stream > Fetch data from a collection in a streaming manner with complex queries for efficient data retrieval. Source: https://docs.apimaker.dev/v4/examples/sys/db/queryByStream.html > **The code in every language** > > Each example is the inside of `main`, written in every [language](https://docs.apimaker.dev/v4/docs/languages/index.html) API Maker runs : pick yours in the tabs, and every page shows it from then on. The types a call takes (`GetAll`, `DeepItem`…) are those of `am` : `from am import GetAll` in Python, `use am::GetAll;` in Rust, `import am.GetAll;` in Java and Kotlin ; PHP and C# have them without an import, Go names them `am.GetAll`. ## Simple query by stream **TypeScript** **Simple query by stream to get data** ```typescript let response = []; await g.sys.db.queryByStream({ instance: "mysql_8", database: "inventory", collection: "customers", find:{ "first_name": "Bob" }, }, (obj) => { response.push(obj); }); ``` ## query by stream [headers] **TypeScript** **query by stream headers** ```typescript let response = []; await g.sys.db.queryByStream({ instance: "mysql_8", database: "inventory", collection: "customers", find:{ "first_name": "Bob" }, headers: { "x-am-response-case": "capitalCase", // noChange | camelCase | capitalCase | constantCase | dotCase | headerCase | noCase | paramCase | pascalCase | pathCase | sentenceCase | snakeCase }, }, (obj) => { response.push(obj); }); ``` ## query by stream [select] **TypeScript** **query by stream select** ```typescript let response = []; await g.sys.db.queryByStream({ instance: "mysql_8", database: "inventory", collection: "customers", find:{ "first_name": "Bob" }, select: "first_name" }, (obj) => { response.push(obj); }); ``` ## query by stream [limit] **TypeScript** **query by stream limit** ```typescript let response = []; await g.sys.db.queryByStream({ instance: "mysql_8", database: "inventory", collection: "customers", find:{ "first_name": "Bob" }, limit: 2 }, (obj) => { response.push(obj); }); ``` ## query by stream[skip] **TypeScript** **query by stream skip** ```typescript let response = []; await g.sys.db.queryByStream({ instance: "mysql_8", database: "inventory", collection: "customers", find:{ "first_name": "Bob" }, skip: 1 }, (obj) => { response.push(obj); }); ``` ## query by stream [sort] **TypeScript** **query by stream sort** ```typescript let response = []; await g.sys.db.queryByStream({ instance: "mysql_8", database: "inventory", collection: "customers", find:{ "first_name": "Bob" }, sort: "first_name" }, (obj) => { response.push(obj); }); ``` ## query by stream [deep] **TypeScript** **query by stream deep** ```typescript let response = []; await g.sys.db.queryByStream({ instance: "mysql_8", database: "inventory", collection: "customers", find:{ "first_name": "Bob" }, deep: [ { s_key: "customer_id", t_instance: "mysql", t_db: "inventory", t_col: "products", t_key: "owner_id", } ], }, (obj) => { response.push(obj); }); ``` ## $lt [less than] query **TypeScript** **less than query** ```typescript let response = []; await g.sys.db.queryByStream({ instance: "mysql_8", database: "inventory", collection: "customers", find: { customer_id: { "$lt": 2 } } }, (obj) => { response.push(obj); }); ``` ## $lte [less than equal] query **TypeScript** **less than equal query** ```typescript let response = []; await g.sys.db.queryByStream({ instance: "mysql_8", database: "inventory", collection: "customers", find: { customer_id: { "$lte": 2 } } }, (obj) => { response.push(obj); }); ``` ## $gt [greater than] query **TypeScript** **greater than query** ```typescript let response = []; await g.sys.db.queryByStream({ instance: "mysql_8", database: "inventory", collection: "customers", find: { customer_id: { "$gt": 2 } } }, (obj) => { response.push(obj); }); ``` ## $gte [greater than equal] query **TypeScript** **greater than equal query** ```typescript let response = []; await g.sys.db.queryByStream({ instance: "mysql_8", database: "inventory", collection: "customers", find: { customer_id: { "$gte": 2 } } }, (obj) => { response.push(obj); }); ``` ## $eq [equal to] query **TypeScript** **$eq query** ```typescript let response = []; await g.sys.db.queryByStream({ instance: "mysql_8", database: "inventory", collection: "customers", find: { customer_id: { "$eq": 2 } } }, (obj) => { response.push(obj); }); ``` ## $ne [not equal to] query **TypeScript** **$ne query** ```typescript let response = []; await g.sys.db.queryByStream({ instance: "mysql_8", database: "inventory", collection: "customers", find: { customer_id: { "$ne": 2 } } }, (obj) => { response.push(obj); }); ``` ## $not [not] query **TypeScript** **$not query** ```typescript let response = []; await g.sys.db.queryByStream({ instance: "mysql_8", database: "inventory", collection: "customers", find: { customer_id: { "$not": { "$in": [1, 2, 3, 4] } } } }, (obj) => { response.push(obj); }); ``` ## $and [and] query **TypeScript** **$and query** ```typescript let response = []; await g.sys.db.queryByStream({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "$and": [ { "customer_id": 2 }, { "zipcode": 7171 } ] } }, (obj) => { response.push(obj); }); ``` ## $or [or] query **TypeScript** **$or query** ```typescript let response = []; await g.sys.db.queryByStream({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "$or": [ { "customer_id": 2 }, { "zipcode": 7171 } ] } }, (obj) => { response.push(obj); }); ``` ## $in [in] query **TypeScript** **$in query** ```typescript let response = []; await g.sys.db.queryByStream({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "customer_id": { "$in": [1, 2] } } }, (obj) => { response.push(obj); }); ``` ## $nin [not in] query **TypeScript** **$nin query** ```typescript let response = []; await g.sys.db.queryByStream({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "customer_id": { "$nin": [1, 2] } } }, (obj) => { response.push(obj); }); ``` ## $like [like] query **TypeScript** **$like query** ```typescript let response = []; await g.sys.db.queryByStream({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "first_name": { "$like": "Bob%" } } }, (obj) => { response.push(obj); }); ``` ## $isNull [null check] with sql databases **TypeScript** **$isNull use** ```typescript let query = await g.sys.db.query({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "first_name": { "$isNull": true } } }); ``` ## MongoDB $in operator in nested find **TypeScript** **$in operator in nested find** ```typescript let response = []; await g.sys.db.queryByStream({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "eventListeners.versions.name": { "$in": [ "Original", "1" ] } } }, (obj) => { response.push(obj); }); ``` ## MongoDB $nin operator in nested find **TypeScript** **$nin operator in nested find** ```typescript let response = []; await g.sys.db.queryByStream({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "eventListeners.versions.name": { "$nin": [ "Original", "1" ] } } }, (obj) => { response.push(obj); }); ``` ## MongoDB $and operator in nested find **TypeScript** **$and operator in nested find** ```typescript let response = []; await g.sys.db.queryByStream({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "$and": [ { "eventListeners.versions.name": "Original" }, { "eventListeners.versions.version": "-1" } ] } }, (obj) => { response.push(obj); }); ``` ## MongoDB $or operator in nested find **TypeScript** **$or operator in nested find** ```typescript let response = []; await g.sys.db.queryByStream({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "$or": [ { "eventListeners.versions.name": "Original" }, { "eventListeners.versions.version": "-1" } ] } }, (obj) => { response.push(obj); }); ``` ## Structure **TypeScript** **query by stream with all params ** ```typescript let response = []; await g.sys.db.queryByStream({ instance: "INSTANCE_NAME", database: 'DB_NAME', collection: "COLLECTION_NAME", find: { "COLUMN_NAME": "VALUE" }, limit: 10, select: "COMMA_SEPARATED_COLUMN_NAMES", deep: [ { s_key: "SOURCE_COLLECTION_COLUMN_NAME", t_instance: "TARGET_INSTANCE_NAME", t_db: "TARGET_DATABASE_NAME", t_col: "TARGET_COLLECTION_NAME", t_key: "TARGET_COLLECTION_COLUMN_NAME", find: { "COLUMN_NAME": "COLUMN_VALUE" }, isMultiple: true, limit: 10, select: "COMMA_SEPARATED_COLUMN_NAMES", skip: 2, sort: "COLUMN_NAME", } ], skip: 1, sort: "COLUMN_NAME", groupBy: "COLUMN_NAME", headers: { "x-am-response-case": "capitalCase", // noChange | camelCase | capitalCase | constantCase | dotCase | headerCase | noCase | paramCase | pascalCase | pathCase | sentenceCase | snakeCase "x-am-response-object-type": "make_flat", // no_action | make_flat "x-am-meta": "true", // true, false "x-am-internationalization": "USER_I18N_ID", "x-am-run-in-sandbox": "2", "x-am-content-type-response": "text/xml", // application/json | text/xml | text/yaml | text/plain | text/html | application/octet-stream "x-am-cache-control": "reset_cache", // no_action | reset_cache "x-am-get-encrypted-data": "get_only_encryption", // no_encryption | get_only_encryption | get_data_and_encryption "x-am-sandbox-timeout": "13000", "x-no-compression": "true", // true | false "x-am-encrypted-payload": "true", // user will send 'true', when payload is encrypted for transfer // Multi-tenant : the tenant of the request, each instance finds it in its own tenants table "x-am-tenant-username": "TENANT_USERNAME", // ex: acme // Authorization headers "x-am-authorization": "AUTHORIZATION_TOKEN", "x-am-user-authorization": "API_USER_TOKEN", "x-aws-authorization": "AWS_TOKEN", "x-google-authorization": "GOOGLE_TOKEN", "x-azure-authorization": "AZURE_TOKEN", }, }, (obj) => { response.push(obj); }); ``` ## Multi-tenant - `instance: "crm::acme"` works on the database of the tenant `acme` of the [multi-tenant](https://docs.apimaker.dev/v4/docs/features/multi-tenant.html) instance `crm`. - With `instance: "crm"`, the call works on the database of the tenant of the request: a custom API called with the [x-am-tenant-username](https://docs.apimaker.dev/v4/docs/apis-all/header/requestHeader.html#x-am-tenant-username) header passes it on to the APIs it calls. A request without a tenant works on the structure database. **TypeScript** **Query the customers of the tenant acme by stream** ```typescript let response = []; await g.sys.db.queryByStream({ instance: "crm::acme", database: "crm", collection: "customers", find: { "first_name": "Bob" } }, (obj) => { response.push(obj); }); ``` ## Without a schema `g.sys.db.gen.queryByStreamGen` takes the same arguments and calls the [query for get data by stream generated API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-query-for-get-data-by-stream-api.html#without-a-schema) : no schema, so the data is read and written as it is in the table, without the conversions, validations and defaults of the schema. | Language | The call | |---|---| | TypeScript | `g.sys.db.gen.queryByStreamGen(…)` | | Python | `g.sys.db.gen.query_by_stream_gen(…)` | | PHP | `$g->sys->db->gen->queryByStreamGen(…)` | | C#, Go | `g.Sys.Db.Gen.QueryByStreamGen(…)` | | Rust | `g.sys.db.query_by_stream_gen(Query::new(…))` | | Java, Kotlin | `g.sys.db.gen.queryByStreamGen(…)` | (The code of this page is also written in Python, PHP, C#, Go, Rust, Java, Kotlin : https://docs.apimaker.dev/v4/examples/sys/db/queryByStream.md) --- # Remove by Query > Delete records from a collection based on specified criteria using API Maker's g.sys.db.removeByQuery method. Source: https://docs.apimaker.dev/v4/examples/sys/db/removeByQuery.html > **The code in every language** > > Each example is the inside of `main`, written in every [language](https://docs.apimaker.dev/v4/docs/languages/index.html) API Maker runs : pick yours in the tabs, and every page shows it from then on. The types a call takes (`GetAll`, `DeepItem`…) are those of `am` : `from am import GetAll` in Python, `use am::GetAll;` in Rust, `import am.GetAll;` in Java and Kotlin ; PHP and C# have them without an import, Go names them `am.GetAll`. `g.sys.db.removeByQuery` calls the [remove by query schema API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-remove-by-query-api.html) of any table from your code, with the same headers and query parameters as over HTTP. It returns the data. The whole envelope (`success`, `statusCode`, `data`, `totalCount`, `errors`…) comes back when `true` is passed as the second argument in TypeScript, and through `full` in the other languages : `g.sys.db.full` (`g.Sys.Db.Full` in C# and Go, `$g->sys->db->full` in PHP). ## Simple removeByQuery **TypeScript** **Remove by query** ```typescript let updateById = await g.sys.db.removeByQuery({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "first_name": "Bob" } }); ``` ## removeByQuery with headers **TypeScript** **Remove by query with headers** ```typescript let updateById = await g.sys.db.removeByQuery({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "first_name": "Bob" }, headers: { "x-am-response-case": "capitalCase", // noChange | camelCase | capitalCase | constantCase | dotCase | headerCase | noCase | paramCase | pascalCase | pathCase | sentenceCase | snakeCase }, }); ``` ## $lt removeByQuery **TypeScript** **$lt Remove by query** ```typescript let updateById = await g.sys.db.removeByQuery({ instance: "mysql_8", database: "inventory", collection: "customers", find: { customer_id: { "$lt": 2 } } }); ``` ## $lte removeByQuery **TypeScript** **$lte Remove by query** ```typescript let updateById = await g.sys.db.removeByQuery({ instance: "mysql_8", database: "inventory", collection: "customers", find: { customer_id: { "$lte": 2 } } }); ``` ## $gt removeByQuery **TypeScript** **$gt Remove by query** ```typescript let updateById = await g.sys.db.removeByQuery({ instance: "mysql_8", database: "inventory", collection: "customers", find: { customer_id: { "$gt": 2 } } }); ``` ## $gte removeByQuery **TypeScript** **$gte Remove by query** ```typescript let updateById = await g.sys.db.removeByQuery({ instance: "mysql_8", database: "inventory", collection: "customers", find: { customer_id: { "$gte": 2 } } }); ``` ## $eq removeByQuery **TypeScript** **$eq Remove by query** ```typescript let updateById = await g.sys.db.removeByQuery({ instance: "mysql_8", database: "inventory", collection: "customers", find: { customer_id: { "$eq": 2 } } }); ``` ## $ne removeByQuery **TypeScript** **$ne Remove by query** ```typescript let updateById = await g.sys.db.removeByQuery({ instance: "mysql_8", database: "inventory", collection: "customers", find: { customer_id: { "$ne": 2 } } }); ``` ## $not removeByQuery **TypeScript** **$not Remove by query** ```typescript let updateById = await g.sys.db.removeByQuery({ instance: "mysql_8", database: "inventory", collection: "customers", find: { customer_id: { "$not": { "$in": [1, 2, 3, 4] } } } }); ``` ## $and removeByQuery **TypeScript** **$and Remove by query** ```typescript let updateById = await g.sys.db.removeByQuery({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "$and": [ { "customer_id": 2 }, { "pincode": 7171 } ] } }); ``` ## $or removeByQuery **TypeScript** **$or Remove by query** ```typescript let updateById = await g.sys.db.removeByQuery({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "$or": [ { "customer_id": 2 }, { "pincode": 7171 } ] } }); ``` ## $in removeByQuery **TypeScript** **$in Remove by query** ```typescript let updateById = await g.sys.db.removeByQuery({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "customer_id": { "$in": [1, 2] } } }); ``` ## $nin removeByQuery **TypeScript** **$nin Remove by query** ```typescript let updateById = await g.sys.db.removeByQuery({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "customer_id": { "$nin": [1, 2] } } }); ``` ## $like removeByQuery **TypeScript** **$nin Remove by query** ```typescript let updateById = await g.sys.db.removeByQuery({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "first_name": { "$like": "Bob%" } } }); ``` ## MongoDB $in operator in nested find **TypeScript** **$in operator in nested find** ```typescript let updateById = await g.sys.db.removeByQuery({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "eventListeners.versions.name": { "$in": [ "Original", "1" ] } } }); ``` ## MongoDB $nin operator in nested find **TypeScript** **$nin operator in nested find** ```typescript let updateById = await g.sys.db.removeByQuery({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "eventListeners.versions.name": { "$nin": [ "Original", "1" ] } } }); ``` ## MongoDB $and operator in nested find **TypeScript** **$and operator in nested find** ```typescript let updateById = await g.sys.db.removeByQuery({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "$and": [ { "eventListeners.versions.name": "Original" }, { "eventListeners.versions.version": "-1" } ] } }); ``` ## MongoDB $or operator in nested find **TypeScript** **$or operator in nested find** ```typescript let updateById = await g.sys.db.removeByQuery({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "$or": [ { "eventListeners.versions.name": "Original" }, { "eventListeners.versions.version": "-1" } ] } }); ``` ## Structure **TypeScript** **Remove by query** ```typescript let updateById = await g.sys.db.removeByQuery({ instance: "INSTANCE_NAME", database: 'DB_NAME', collection: "COLLECTION_NAME", find: { "COLUMN_NAME": "VALUE" }, headers: { "x-am-response-case": "capitalCase", // noChange | camelCase | capitalCase | constantCase | dotCase | headerCase | noCase | paramCase | pascalCase | pathCase | sentenceCase | snakeCase "x-am-response-object-type": "make_flat", // no_action | make_flat "x-am-meta": "true", // true, false "x-am-internationalization": "USER_I18N_ID", "x-am-run-in-sandbox": "2", "x-am-content-type-response": "text/xml", // application/json | text/xml | text/yaml | text/plain | text/html | application/octet-stream "x-am-cache-control": "reset_cache", // no_action | reset_cache "x-am-get-encrypted-data": "get_only_encryption", // no_encryption | get_only_encryption | get_data_and_encryption "x-am-sandbox-timeout": "13000", "x-no-compression": "true", // true | false "x-am-encrypted-payload": "true", // user will send 'true', when payload is encrypted for transfer // Multi-tenant : the tenant of the request, each instance finds it in its own tenants table "x-am-tenant-username": "TENANT_USERNAME", // ex: acme // Authorization headers "x-am-authorization": "AUTHORIZATION_TOKEN", "x-am-user-authorization": "API_USER_TOKEN", "x-aws-authorization": "AWS_TOKEN", "x-google-authorization": "GOOGLE_TOKEN", "x-azure-authorization": "AZURE_TOKEN", }, }); ``` ## Multi-tenant - `instance: "crm::acme"` works on the database of the tenant `acme` of the [multi-tenant](https://docs.apimaker.dev/v4/docs/features/multi-tenant.html) instance `crm`. - With `instance: "crm"`, the call works on the database of the tenant of the request: a custom API called with the [x-am-tenant-username](https://docs.apimaker.dev/v4/docs/apis-all/header/requestHeader.html#x-am-tenant-username) header passes it on to the APIs it calls. A request without a tenant works on the structure database. **TypeScript** **Remove customers of the tenant acme by query** ```typescript let removeByQuery = await g.sys.db.removeByQuery({ instance: "crm::acme", database: "crm", collection: "customers", find: { "first_name": "Bob" } }); ``` ## Without a schema `g.sys.db.gen.removeByQueryGen` takes the same arguments and calls the [remove by query generated API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-remove-by-query-api.html#without-a-schema) : no schema, so the data is read and written as it is in the table, without the conversions, validations and defaults of the schema. | Language | The call | |---|---| | TypeScript | `g.sys.db.gen.removeByQueryGen(…)` | | Python | `g.sys.db.gen.remove_by_query_gen(…)` | | PHP | `$g->sys->db->gen->removeByQueryGen(…)` | | C#, Go | `g.Sys.Db.Gen.RemoveByQueryGen(…)` | | Rust | `g.sys.db.remove_by_query_gen(RemoveByQuery::new(…))` | | Java, Kotlin | `g.sys.db.gen.removeByQueryGen(…)` | ## Related - [Remove by query API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-remove-by-query-api.html) · [Generated API from code](https://docs.apimaker.dev/v4/examples/sys/db/removeByQuery.html#without-a-schema) · [The global object g](https://docs.apimaker.dev/v4/docs/pre-defined-terms/global-object-g.html) (The code of this page is also written in Python, PHP, C#, Go, Rust, Java, Kotlin : https://docs.apimaker.dev/v4/examples/sys/db/removeByQuery.md) --- # Aggregate > Perform aggregation operations like count, sum, average, etc., on data within a collection using API Maker. Source: https://docs.apimaker.dev/v4/examples/sys/db/aggregate.html > **The code in every language** > > Each example is the inside of `main`, written in every [language](https://docs.apimaker.dev/v4/docs/languages/index.html) API Maker runs : pick yours in the tabs, and every page shows it from then on. The types a call takes (`GetAll`, `DeepItem`…) are those of `am` : `from am import GetAll` in Python, `use am::GetAll;` in Rust, `import am.GetAll;` in Java and Kotlin ; PHP and C# have them without an import, Go names them `am.GetAll`. `g.sys.db.aggregate` calls the [aggregate schema API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-aggregate-api.html) of any table from your code, with the same headers and query parameters as over HTTP. It returns the data. The whole envelope (`success`, `statusCode`, `data`, `totalCount`, `errors`…) comes back when `true` is passed as the second argument in TypeScript, and through `full` in the other languages : `g.sys.db.full` (`g.Sys.Db.Full` in C# and Go, `$g->sys->db->full` in PHP). Aggregation runs on MongoDB. `aggregateQuery` is a pipeline of MongoDB : every stage and operator of the [MongoDB manual](https://www.mongodb.com/docs/manual/reference/operator/aggregation-pipeline/) works, so this page shows three common shapes. ## Group, filter and count : $group, $match **TypeScript** **MongoDB Basic aggregation** ```typescript let aggregate = await g.sys.db.aggregate({ instance: "mongodb", database: "inventory", collection: "customers", aggregateQuery: [ { "$group": { "_id": "$_id", "total": { "$sum": "$customer_id" } } }, { "$match": { "total": { "$gt": 1 } } }, { "$sort": { "total": -1 } }, { "$count": "CountValue" } ] }); ``` ## Several groupings at once : $facet and $bucket **TypeScript** **MongoDB $facet with multiple $bucket** ```typescript let aggregate = await g.sys.db.aggregate({ instance: "mongodb", database: "inventory", collection: "customers", aggregateQuery:[ { "$facet": { "price": [ { "$bucket": { "groupBy": "$price", "boundaries": [10000,20000,30000,40000,50000,60000,70000,80000], "default": "Other", "output": { "count": { "$sum": 1 }, "product_details": { "$push": { "name": "$name", "price": "$price" } } } } } ], "categories": [ { "$bucket": { "groupBy": "$category_id", "boundaries": [10000,20000,30000,40000,50000,60000,70000,80000], "default": "Other", "output": { "count": { "$sum": 1 }, "product_details": { "$push": { "name": "$name", "id": "$id", "category_id": "$category_id" } } } } } ] } } ] }); ``` ## Join another collection : $lookup **TypeScript** **MongoDB $lookup** ```typescript let aggregate = await g.sys.db.aggregate({ instance: "mongodb", database: "inventory", collection: "customers", aggregateQuery:[ { "$lookup": { "from": "products", "localField": "customer_id", "foreignField": "owner_id", "as": "customer_data" } } ] }); ``` ## Multi-tenant - `instance: "crm::acme"` works on the database of the tenant `acme` of the [multi-tenant](https://docs.apimaker.dev/v4/docs/features/multi-tenant.html) instance `crm`. - With `instance: "crm"`, the call works on the database of the tenant of the request: a custom API called with the [x-am-tenant-username](https://docs.apimaker.dev/v4/docs/apis-all/header/requestHeader.html#x-am-tenant-username) header passes it on to the APIs it calls. A request without a tenant works on the structure database. **TypeScript** **Aggregate the customers of the tenant acme (MongoDB)** ```typescript let aggregate = await g.sys.db.aggregate({ instance: "crm::acme", database: "crm", collection: "customers", aggregateQuery: [{ "$group": { "_id": "$city", "customers": { "$sum": 1 } } }] }); ``` ## Without a schema `g.sys.db.gen.aggregateGen` takes the same arguments and calls the [aggregate generated API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-aggregate-api.html#without-a-schema) : no schema, so the data is read and written as it is in the table, without the conversions, validations and defaults of the schema. | Language | The call | |---|---| | TypeScript | `g.sys.db.gen.aggregateGen(…)` | | Python | `g.sys.db.gen.aggregate_gen(…)` | | PHP | `$g->sys->db->gen->aggregateGen(…)` | | C#, Go | `g.Sys.Db.Gen.AggregateGen(…)` | | Rust | `g.sys.db.aggregate_gen(Aggregate::new(…))` | | Java, Kotlin | `g.sys.db.gen.aggregateGen(…)` | ## Related - [Aggregate API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-aggregate-api.html) · [Generated API from code](https://docs.apimaker.dev/v4/examples/sys/db/aggregate.html#without-a-schema) · [The global object g](https://docs.apimaker.dev/v4/docs/pre-defined-terms/global-object-g.html) (The code of this page is also written in Python, PHP, C#, Go, Rust, Java, Kotlin : https://docs.apimaker.dev/v4/examples/sys/db/aggregate.md) --- # Count > Get the total number of records in a collection or matching a specific query using API Maker's g.sys.db.count method. Source: https://docs.apimaker.dev/v4/examples/sys/db/count.html > **The code in every language** > > Each example is the inside of `main`, written in every [language](https://docs.apimaker.dev/v4/docs/languages/index.html) API Maker runs : pick yours in the tabs, and every page shows it from then on. The types a call takes (`GetAll`, `DeepItem`…) are those of `am` : `from am import GetAll` in Python, `use am::GetAll;` in Rust, `import am.GetAll;` in Java and Kotlin ; PHP and C# have them without an import, Go names them `am.GetAll`. `g.sys.db.count` calls the [count schema API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-count-api.html) of any table from your code, with the same headers and query parameters as over HTTP. It returns the data. The whole envelope (`success`, `statusCode`, `data`, `totalCount`, `errors`…) comes back when `true` is passed as the second argument in TypeScript, and through `full` in the other languages : `g.sys.db.full` (`g.Sys.Db.Full` in C# and Go, `$g->sys->db->full` in PHP). ## Simple get count **TypeScript** **Simple get count** ```typescript let count = await g.sys.db.count({ instance: "mysql_8", database: "inventory", collection: "customers", }); ``` ## get count [headers] **TypeScript** **get count with headers** ```typescript let count = await g.sys.db.count({ instance: "mysql_8", database: "inventory", collection: "customers", headers: { "x-am-response-case": "capitalCase", // noChange | camelCase | capitalCase | constantCase | dotCase | headerCase | noCase | paramCase | pascalCase | pathCase | sentenceCase | snakeCase }, }); ``` ## get count [find] **TypeScript** **Simple find** ```typescript let count = await g.sys.db.count({ instance: "mysql_8", database: "inventory", collection: "customers", find:{ "first_name": "Bob" } }); ``` ## $gt **TypeScript** **$gt** ```typescript let count = await g.sys.db.count({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "customer_id": { "$gt": 4 } } }); ``` ## $gte **TypeScript** **$gte** ```typescript let count = await g.sys.db.count({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "customer_id": { "$gte": 4 } } }); ``` ## $lt **TypeScript** **$lt** ```typescript let count = await g.sys.db.count({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "customer_id": { "$lt": 4 } } }); ``` ## $lte **TypeScript** **$lte** ```typescript let count = await g.sys.db.count({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "customer_id": { "$lte": 4 } } }); ``` ## $eq **TypeScript** **$eq** ```typescript let count = await g.sys.db.count({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "first_name": { "$eq": "Bob" } } }); ``` ## $ne **TypeScript** **$ne** ```typescript let count = await g.sys.db.count({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "first_name": { "$ne": "Bob" } } }); ``` ## $in **TypeScript** **$in** ```typescript let count = await g.sys.db.count({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "customer_id": { "$in": [1, 2] } } }); ``` ## $nin **TypeScript** **$nin** ```typescript let count = await g.sys.db.count({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "customer_id": { "$nin": [1, 2] } } }); ``` ## $and **TypeScript** **$and** ```typescript let count = await g.sys.db.count({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "$and": [ { "employee_Details.emp_Id": 1 }, { "city": "Baroda" } ] } }); ``` ## $or **TypeScript** **$or** ```typescript let count = await g.sys.db.count({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "$or": [ { "state": "Gujarat" }, { "city": "Baroda" } ] } }); ``` ## $like **TypeScript** **$like** ```typescript let count = await g.sys.db.count({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "first_name": { "$like": "%Mall%" } } }); ``` ## floating value support **TypeScript** **floating value support** ```typescript let count = await g.sys.db.count({ instance: "mysql_8", database: "inventory", collection: "customers", find: { "customer_id":{ "$gt": 2.2 } } }); ``` ## Structure **TypeScript** **Count method** ```typescript let count = await g.sys.db.count({ instance: "INSTANCE_NAME", database: 'DB_NAME', collection: "COLLECTION_NAME", find: { "COLUMN_NAME": "VALUE", }, headers: { "x-am-response-case": "capitalCase", // noChange | camelCase | capitalCase | constantCase | dotCase | headerCase | noCase | paramCase | pascalCase | pathCase | sentenceCase | snakeCase "x-am-response-object-type": "make_flat", // no_action | make_flat "x-am-meta": "true", // true, false "x-am-internationalization": "USER_I18N_ID", "x-am-run-in-sandbox": "2", "x-am-content-type-response": "text/xml", // application/json | text/xml | text/yaml | text/plain | text/html | application/octet-stream "x-am-cache-control": "reset_cache", // no_action | reset_cache "x-am-get-encrypted-data": "get_only_encryption", // no_encryption | get_only_encryption | get_data_and_encryption "x-am-sandbox-timeout": "13000", "x-no-compression": "true", // true | false "x-am-encrypted-payload": "true", // user will send 'true', when payload is encrypted for transfer // Multi-tenant : the tenant of the request, each instance finds it in its own tenants table "x-am-tenant-username": "TENANT_USERNAME", // ex: acme // Authorization headers "x-am-authorization": "AUTHORIZATION_TOKEN", "x-am-user-authorization": "API_USER_TOKEN", "x-aws-authorization": "AWS_TOKEN", "x-google-authorization": "GOOGLE_TOKEN", "x-azure-authorization": "AZURE_TOKEN", }, }); ``` ## Multi-tenant - `instance: "crm::acme"` works on the database of the tenant `acme` of the [multi-tenant](https://docs.apimaker.dev/v4/docs/features/multi-tenant.html) instance `crm`. - With `instance: "crm"`, the call works on the database of the tenant of the request: a custom API called with the [x-am-tenant-username](https://docs.apimaker.dev/v4/docs/apis-all/header/requestHeader.html#x-am-tenant-username) header passes it on to the APIs it calls. A request without a tenant works on the structure database. **TypeScript** **Count the customers of the tenant acme** ```typescript let count = await g.sys.db.count({ instance: "crm::acme", database: "crm", collection: "customers", find: { "first_name": "Bob" } }); ``` ## Without a schema `g.sys.db.gen.countGen` takes the same arguments and calls the [count generated API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-count-api.html#without-a-schema) : no schema, so the data is read and written as it is in the table, without the conversions, validations and defaults of the schema. | Language | The call | |---|---| | TypeScript | `g.sys.db.gen.countGen(…)` | | Python | `g.sys.db.gen.count_gen(…)` | | PHP | `$g->sys->db->gen->countGen(…)` | | C#, Go | `g.Sys.Db.Gen.CountGen(…)` | | Rust | `g.sys.db.count_gen(Count::new(…))` | | Java, Kotlin | `g.sys.db.gen.countGen(…)` | ## Related - [Count API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-count-api.html) · [Generated API from code](https://docs.apimaker.dev/v4/examples/sys/db/count.html#without-a-schema) · [The global object g](https://docs.apimaker.dev/v4/docs/pre-defined-terms/global-object-g.html) (The code of this page is also written in Python, PHP, C#, Go, Rust, Java, Kotlin : https://docs.apimaker.dev/v4/examples/sys/db/count.md) --- # Distinct > Retrieve distinct values for a specified field in a collection using API Maker's g.sys.db.distinct method. Source: https://docs.apimaker.dev/v4/examples/sys/db/distinct.html > **The code in every language** > > Each example is the inside of `main`, written in every [language](https://docs.apimaker.dev/v4/docs/languages/index.html) API Maker runs : pick yours in the tabs, and every page shows it from then on. The types a call takes (`GetAll`, `DeepItem`…) are those of `am` : `from am import GetAll` in Python, `use am::GetAll;` in Rust, `import am.GetAll;` in Java and Kotlin ; PHP and C# have them without an import, Go names them `am.GetAll`. `g.sys.db.distinct` calls the [distinct schema API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-distinct-api.html) of any table from your code, with the same headers and query parameters as over HTTP. It returns the data. The whole envelope (`success`, `statusCode`, `data`, `totalCount`, `errors`…) comes back when `true` is passed as the second argument in TypeScript, and through `full` in the other languages : `g.sys.db.full` (`g.Sys.Db.Full` in C# and Go, `$g->sys->db->full` in PHP). ## Simple distinct **TypeScript** **Simple distinct** ```typescript let distinct = await g.sys.db.distinct({ instance: "mysql_8", database: "inventory", collection: "customers", distinctField: "first_name" }); ``` ## distinct with header **TypeScript** **distinct with header** ```typescript let distinct = await g.sys.db.distinct({ instance: "mysql_8", database: "inventory", collection: "customers", distinctField: "first_name", headers: { "x-am-response-case": "capitalCase", // noChange | camelCase | capitalCase | constantCase | dotCase | headerCase | noCase | paramCase | pascalCase | pathCase | sentenceCase | snakeCase }, }); ``` ## distinct with order ### ascending **TypeScript** **distinct with order** ```typescript let distinct = await g.sys.db.distinct({ instance: "mysql_8", database: "inventory", collection: "customers", distinctField: "first_name", order: "asc" }); ``` ### descending **TypeScript** **distinct with header** ```typescript let distinct = await g.sys.db.distinct({ instance: "mysql_8", database: "inventory", collection: "customers", distinctField: "first_name", order: "desc" }); ``` ## Structure **TypeScript** **Distinct method** ```typescript let distinct = await g.sys.db.distinct({ instance: "INSTANCE_NAME", database: 'DB_NAME', collection: "COLLECTION_NAME", distinctField: "COLUMN_NAME", order: "asc", // asc | desc headers: { "x-am-response-case": "capitalCase", // noChange | camelCase | capitalCase | constantCase | dotCase | headerCase | noCase | paramCase | pascalCase | pathCase | sentenceCase | snakeCase "x-am-response-object-type": "make_flat", // no_action | make_flat "x-am-meta": "true", // true, false "x-am-internationalization": "USER_I18N_ID", "x-am-run-in-sandbox": "2", "x-am-content-type-response": "text/xml", // application/json | text/xml | text/yaml | text/plain | text/html | application/octet-stream "x-am-cache-control": "reset_cache", // no_action | reset_cache "x-am-get-encrypted-data": "get_only_encryption", // no_encryption | get_only_encryption | get_data_and_encryption "x-am-sandbox-timeout": "13000", "x-no-compression": "true", // true | false "x-am-encrypted-payload": "true", // user will send 'true', when payload is encrypted for transfer // Multi-tenant : the tenant of the request, each instance finds it in its own tenants table "x-am-tenant-username": "TENANT_USERNAME", // ex: acme // Authorization headers "x-am-authorization": "AUTHORIZATION_TOKEN", "x-am-user-authorization": "API_USER_TOKEN", "x-aws-authorization": "AWS_TOKEN", "x-google-authorization": "GOOGLE_TOKEN", "x-azure-authorization": "AZURE_TOKEN", }, }); ``` ## Multi-tenant - `instance: "crm::acme"` works on the database of the tenant `acme` of the [multi-tenant](https://docs.apimaker.dev/v4/docs/features/multi-tenant.html) instance `crm`. - With `instance: "crm"`, the call works on the database of the tenant of the request: a custom API called with the [x-am-tenant-username](https://docs.apimaker.dev/v4/docs/apis-all/header/requestHeader.html#x-am-tenant-username) header passes it on to the APIs it calls. A request without a tenant works on the structure database. **TypeScript** **Distinct first names of the customers of the tenant acme** ```typescript let distinct = await g.sys.db.distinct({ instance: "crm::acme", database: "crm", collection: "customers", distinctField: "first_name" }); ``` ## Without a schema `g.sys.db.gen.distinctGen` takes the same arguments and calls the [distinct generated API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-distinct-api.html#without-a-schema) : no schema, so the data is read and written as it is in the table, without the conversions, validations and defaults of the schema. | Language | The call | |---|---| | TypeScript | `g.sys.db.gen.distinctGen(…)` | | Python | `g.sys.db.gen.distinct_gen(…)` | | PHP | `$g->sys->db->gen->distinctGen(…)` | | C#, Go | `g.Sys.Db.Gen.DistinctGen(…)` | | Rust | `g.sys.db.distinct_gen(Distinct::new(…))` | | Java, Kotlin | `g.sys.db.gen.distinctGen(…)` | ## Related - [Distinct API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-distinct-api.html) · [Generated API from code](https://docs.apimaker.dev/v4/examples/sys/db/distinct.html#without-a-schema) · [The global object g](https://docs.apimaker.dev/v4/docs/pre-defined-terms/global-object-g.html) (The code of this page is also written in Python, PHP, C#, Go, Rust, Java, Kotlin : https://docs.apimaker.dev/v4/examples/sys/db/distinct.md) --- # Distinct with Query > Fetch distinct values for a field based on a query filter using API Maker's g.sys.db.distinctWithQuery method. Source: https://docs.apimaker.dev/v4/examples/sys/db/distinctQuery.html > **The code in every language** > > Each example is the inside of `main`, written in every [language](https://docs.apimaker.dev/v4/docs/languages/index.html) API Maker runs : pick yours in the tabs, and every page shows it from then on. The types a call takes (`GetAll`, `DeepItem`…) are those of `am` : `from am import GetAll` in Python, `use am::GetAll;` in Rust, `import am.GetAll;` in Java and Kotlin ; PHP and C# have them without an import, Go names them `am.GetAll`. `g.sys.db.distinctQuery` calls the [distinct with query schema API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-distinct-with-query-api.html) of any table from your code, with the same headers and query parameters as over HTTP. It returns the data. The whole envelope (`success`, `statusCode`, `data`, `totalCount`, `errors`…) comes back when `true` is passed as the second argument in TypeScript, and through `full` in the other languages : `g.sys.db.full` (`g.Sys.Db.Full` in C# and Go, `$g->sys->db->full` in PHP). ## Simple get distinctWithQuery **TypeScript** **Simple distinctWithQuery** ```typescript let distinctQuery = await g.sys.db.distinctQuery({ instance: "mysql_8", database: "inventory", collection: "customers", distinctField: "first_name" }); ``` ## distinctWithQuery with multiple distinctField **TypeScript** **distinctWithQuery with multiple distinctField** ```typescript let distinctQuery = await g.sys.db.distinctQuery({ instance: "mysql_8", database: "inventory", collection: "customers", distinctField: "first_name,last_name" }); ``` ## distinctWithQuery with headers **TypeScript** **distinctWithQuery with headers** ```typescript let distinctQuery = await g.sys.db.distinctQuery({ instance: "mysql_8", database: "inventory", collection: "customers", distinctField: "first_name", headers: { "x-am-response-case": "capitalCase", // noChange | camelCase | capitalCase | constantCase | dotCase | headerCase | noCase | paramCase | pascalCase | pathCase | sentenceCase | snakeCase }, }); ``` ## distinctWithQuery with order ### ascending **TypeScript** **distinctWithQuery with ascending order** ```typescript let distinctQuery = await g.sys.db.distinctQuery({ instance: "mysql_8", database: "inventory", collection: "customers", distinctField: "first_name", order: "asc" }); ``` ### descending **TypeScript** **distinctWithQuery with descending order** ```typescript let distinctQuery = await g.sys.db.distinctQuery({ instance: "mysql_8", database: "inventory", collection: "customers", distinctField: "first_name", order: "desc" }); ``` ## distinctWithQuery with find **TypeScript** **distinctWithQuery with find** ```typescript let distinctQuery = await g.sys.db.distinctQuery({ instance: "mysql_8", database: "inventory", collection: "customers", distinctField: "first_name", find: { first_name: "Bob" } }); ``` ## $lt distinctWithQuery **TypeScript** **distinctWithQuery with $lt** ```typescript let distinctQuery = await g.sys.db.distinctQuery({ instance: "mysql_8", database: "inventory", collection: "customers", distinctField: "first_name", find: { customer_id: { "$lt": 2 } } }); ``` ## $lte distinctWithQuery **TypeScript** **distinctWithQuery with $lte** ```typescript let distinctQuery = await g.sys.db.distinctQuery({ instance: "mysql_8", database: "inventory", collection: "customers", distinctField: "first_name", find: { customer_id: { "$lte": 2 } } }); ``` ## $gt distinctWithQuery **TypeScript** **distinctWithQuery with $gt** ```typescript let distinctQuery = await g.sys.db.distinctQuery({ instance: "mysql_8", database: "inventory", collection: "customers", distinctField: "first_name", find: { customer_id: { "$gt": 2 } } }); ``` ## $gte distinctWithQuery **TypeScript** **distinctWithQuery with $gte** ```typescript let distinctQuery = await g.sys.db.distinctQuery({ instance: "mysql_8", database: "inventory", collection: "customers", distinctField: "first_name", find: { customer_id: { "$gte": 2 } } }); ``` ## $eq distinctWithQuery **TypeScript** **distinctWithQuery with $eq** ```typescript let distinctQuery = await g.sys.db.distinctQuery({ instance: "mysql_8", database: "inventory", collection: "customers", distinctField: "first_name", find: { customer_id: { "$eq": 2 } } }); ``` ## $ne distinctWithQuery **TypeScript** **distinctWithQuery with $ne** ```typescript let distinctQuery = await g.sys.db.distinctQuery({ instance: "mysql_8", database: "inventory", collection: "customers", distinctField: "first_name", find: { customer_id: { "$ne": 2 } } }); ``` ## $not distinctWithQuery **TypeScript** **distinctWithQuery with $not** ```typescript let distinctQuery = await g.sys.db.distinctQuery({ instance: "mysql_8", database: "inventory", collection: "customers", distinctField: "first_name", find: { customer_id: { "$not": { "$in": [1,2,3] } } } }); ``` ## $and distinctWithQuery **TypeScript** **distinctWithQuery with $and** ```typescript let distinctQuery = await g.sys.db.distinctQuery({ instance: "mysql_8", database: "inventory", collection: "customers", distinctField: "first_name", find: { "$and": [ { "customer_id": 1 }, { "zipcode": 382345 } ] } }); ``` ## $or distinctWithQuery **TypeScript** **distinctWithQuery with $or** ```typescript let distinctQuery = await g.sys.db.distinctQuery({ instance: "mysql_8", database: "inventory", collection: "customers", distinctField: "first_name", find: { "$or": [ { "customer_id": 1 }, { "zipcode": 382345 } ] } }); ``` ## $in distinctWithQuery **TypeScript** **distinctWithQuery with $in** ```typescript let distinctQuery = await g.sys.db.distinctQuery({ instance: "mysql_8", database: "inventory", collection: "customers", distinctField: "first_name", find: { customer_id: { "$in": [1, 2,3] } } }); ``` ## $nin distinctWithQuery **TypeScript** **distinctWithQuery with $nin** ```typescript let distinctQuery = await g.sys.db.distinctQuery({ instance: "mysql_8", database: "inventory", collection: "customers", distinctField: "first_name", find: { customer_id: { "$nin": [1, 2,3] } } }); ``` ## $like distinctWithQuery **TypeScript** **distinctWithQuery with $like** ```typescript let distinctQuery = await g.sys.db.distinctQuery({ instance: "mysql_8", database: "inventory", collection: "customers", distinctField: "first_name", find: { first_name: { "$like": "Bob%" } } }); ``` ## Structure **TypeScript** **Distinct Query** ```typescript let distinctQuery = await g.sys.db.distinctQuery({ instance: "INSTANCE_NAME", database: 'DB_NAME', collection: "COLLECTION_NAME", distinctField: "COLUMN_NAME", order: "asc", // asc | desc find: { "COLUMN_NAME": "VALUE", }, headers: { "x-am-response-case": "capitalCase", // noChange | camelCase | capitalCase | constantCase | dotCase | headerCase | noCase | paramCase | pascalCase | pathCase | sentenceCase | snakeCase "x-am-response-object-type": "make_flat", // no_action | make_flat "x-am-meta": "true", // true, false "x-am-internationalization": "USER_I18N_ID", "x-am-run-in-sandbox": "2", "x-am-content-type-response": "text/xml", // application/json | text/xml | text/yaml | text/plain | text/html | application/octet-stream "x-am-cache-control": "reset_cache", // no_action | reset_cache "x-am-get-encrypted-data": "get_only_encryption", // no_encryption | get_only_encryption | get_data_and_encryption "x-am-sandbox-timeout": "13000", "x-no-compression": "true", // true | false "x-am-encrypted-payload": "true", // user will send 'true', when payload is encrypted for transfer // Multi-tenant : the tenant of the request, each instance finds it in its own tenants table "x-am-tenant-username": "TENANT_USERNAME", // ex: acme // Authorization headers "x-am-authorization": "AUTHORIZATION_TOKEN", "x-am-user-authorization": "API_USER_TOKEN", "x-aws-authorization": "AWS_TOKEN", "x-google-authorization": "GOOGLE_TOKEN", "x-azure-authorization": "AZURE_TOKEN", }, }); ``` ## Multi-tenant - `instance: "crm::acme"` works on the database of the tenant `acme` of the [multi-tenant](https://docs.apimaker.dev/v4/docs/features/multi-tenant.html) instance `crm`. - With `instance: "crm"`, the call works on the database of the tenant of the request: a custom API called with the [x-am-tenant-username](https://docs.apimaker.dev/v4/docs/apis-all/header/requestHeader.html#x-am-tenant-username) header passes it on to the APIs it calls. A request without a tenant works on the structure database. **TypeScript** **Distinct first names of some customers of the tenant acme** ```typescript let distinctQuery = await g.sys.db.distinctQuery({ instance: "crm::acme", database: "crm", collection: "customers", distinctField: "first_name", find: { "last_name": "Lin" } }); ``` ## Without a schema `g.sys.db.gen.distinctQueryGen` takes the same arguments and calls the [distinct with query generated API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-distinct-with-query-api.html#without-a-schema) : no schema, so the data is read and written as it is in the table, without the conversions, validations and defaults of the schema. | Language | The call | |---|---| | TypeScript | `g.sys.db.gen.distinctQueryGen(…)` | | Python | `g.sys.db.gen.distinct_query_gen(…)` | | PHP | `$g->sys->db->gen->distinctQueryGen(…)` | | C#, Go | `g.Sys.Db.Gen.DistinctQueryGen(…)` | | Rust | `g.sys.db.distinct_query_gen(Distinct::new(…))` | | Java, Kotlin | `g.sys.db.gen.distinctQueryGen(…)` | ## Related - [Distinct with query API](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-distinct-with-query-api.html) · [Generated API from code](https://docs.apimaker.dev/v4/examples/sys/db/distinctQuery.html#without-a-schema) · [The global object g](https://docs.apimaker.dev/v4/docs/pre-defined-terms/global-object-g.html) (The code of this page is also written in Python, PHP, C#, Go, Rust, Java, Kotlin : https://docs.apimaker.dev/v4/examples/sys/db/distinctQuery.md) --- # System APIs from Code > Every system API of API Maker called from your code with g.sys.system and g.sys.cache - encryption, hashing, tokens, secrets, plain queries, indexes, events, validations, external APIs and Redis - each with its page and its code in eight languages. Source: https://docs.apimaker.dev/v4/examples/sys/system/system.html Your code calls every [system API](https://docs.apimaker.dev/v4/docs/apis-all/overview.html#system-apis) through `g.sys.system` and `g.sys.cache`, whatever the settings of the API say about HTTP callers. Each API has one page : the HTTP call first, then **From code** with the code in eight languages. ## g.sys.system | Method | What it does | Page | |---|---|---| | `encrypt`, `decrypt` | Encrypt and decrypt a value with the transfer key of the secret, or your own | [Encrypt](https://docs.apimaker.dev/v4/docs/apis-all/system-apis/system-generated-encrypt-data-api.html#from-code) · [Decrypt](https://docs.apimaker.dev/v4/docs/apis-all/system-apis/system-generated-decrypt-data-api.html#from-code) | | `hash` | The hash a hashed column stores, to look a row up | [Hash data](https://docs.apimaker.dev/v4/docs/apis-all/system-apis/system-generated-hash-data-api.html#look-up-a-hashed-column) | | `getToken` | The token of an API user, or of a person | [Get token](https://docs.apimaker.dev/v4/docs/apis-all/system-apis/system-generated-token-api.html#from-code) | | `getSecret` | A key of a secret, or several | [Get secret](https://docs.apimaker.dev/v4/docs/apis-all/system-apis/system-generated-get-secret-by-name-api.html#from-code) | | `executeQuery` | A plain query of the database : SQL, or a command of MongoDB | [Examples](https://docs.apimaker.dev/v4/examples/sys/system/executeQuery.html) · [Execute plain query](https://docs.apimaker.dev/v4/docs/apis-all/system-apis/system-generated-execute-plain-query-api.html) | | `callExternalApi` | Call another API over HTTP : one call, several in parallel or in sequence, files | [Examples](https://docs.apimaker.dev/v4/examples/sys/system/callExternalApi.html) · [Call external API](https://docs.apimaker.dev/v4/docs/apis-all/system-apis/system-generated-call-external-api.html#from-code) | | `getTableMeta` | The columns of a table, as its database has them | [Get table meta](https://docs.apimaker.dev/v4/docs/apis-all/system-apis/system-generated-get-table-meta-api.html#from-code) | | `createIndexes`, `dropIndexes`, `getIndexes` | Indexes in the same words on every database | [Create](https://docs.apimaker.dev/v4/docs/apis-all/system-apis/system-generated-create-indexes-api.html#from-code) · [Drop](https://docs.apimaker.dev/v4/docs/apis-all/system-apis/system-generated-drop-indexes-api.html#from-code) · [Get](https://docs.apimaker.dev/v4/docs/apis-all/system-apis/system-generated-get-indexes-api.html#from-code) | | `emitEvent`, `emitEventWS` | Run the listeners of an event, or tell WebSocket clients | [Emit event](https://docs.apimaker.dev/v4/docs/apis-all/system-apis/system-generated-emit-event-api.html#from-code) · [Emit WebSocket event](https://docs.apimaker.dev/v4/docs/apis-all/system-apis/system-generated-emit-event-ws-api.html#from-code) | | `isValidDataForTable`, `isValidDataForCustomAPI` | Check data against a schema, or the body of a custom API, before you use it | [For a table](https://docs.apimaker.dev/v4/docs/apis-all/system-apis/system-generated-is-valid-data-for-table-api.html#from-code) · [For a custom API](https://docs.apimaker.dev/v4/docs/apis-all/system-apis/system-generated-is-valid-data-for-custom-api.html#from-code) | | `isValidConnectionString` | Try a connection string before you save it | [Is valid connection string](https://docs.apimaker.dev/v4/docs/apis-all/system-apis/system-generated-is-valid-connection-string-api.html#from-code) | | `multiTenantInstanceUpdated` | Tell every server that the connection of a tenant changed | [Multi tenant instance updated](https://docs.apimaker.dev/v4/docs/apis-all/system-apis/system-generated-multi-tenant-instance-updated-api.html#from-code) | ## g.sys.cache | Method | What it does | Page | |---|---|---| | `getKey`, `setKey`, `removeKey` | Keys of your own in Redis, with a time to live | [Get](https://docs.apimaker.dev/v4/docs/apis-all/system-apis/system-generated-get-redis-key-api.html#from-code) · [Set](https://docs.apimaker.dev/v4/docs/apis-all/system-apis/system-generated-set-redis-key-api.html#from-code) · [Remove](https://docs.apimaker.dev/v4/docs/apis-all/system-apis/system-generated-remove-redis-key-api.html#from-code) | | `resetCacheDB`, `resetCacheCustomApis`, `resetCacheSystemApis` | Drop the cached answers of a table, a custom API or a system API | [Database](https://docs.apimaker.dev/v4/docs/apis-all/system-apis/system-generated-reset-redis-cache-db-api.html#from-code) · [Custom API](https://docs.apimaker.dev/v4/docs/apis-all/system-apis/system-generated-reset-redis-cache-custom-api.html#from-code) · [System API](https://docs.apimaker.dev/v4/docs/apis-all/system-apis/system-generated-reset-redis-cache-system-api.html#from-code) | ## Good to know - A call answers `data`, and throws the errors : the caller of your API gets them. In the languages other than TypeScript, `full` gives the whole response envelope (`g.sys.system.full` in Python…) : see the page of your [language](https://docs.apimaker.dev/v4/docs/languages/index.html). - Every call takes the [request headers](https://docs.apimaker.dev/v4/docs/apis-all/header/requestHeader.html) of its HTTP form, such as `x-am-tenant-username`. --- # Execute Query Example > Learn how to run SQL queries with API Maker’s executeQuery function, including DDL, DML, DQL, and joins. Source: https://docs.apimaker.dev/v4/examples/sys/system/executeQuery.html > **The code in every language** > > Each example is the inside of `main`, written in every [language](https://docs.apimaker.dev/v4/docs/languages/index.html) API Maker runs : pick yours in the tabs, and every page shows it from then on. The types a call takes (`GetAll`, `DeepItem`…) are those of `am` : `from am import GetAll` in Python, `use am::GetAll;` in Rust, `import am.GetAll;` in Java and Kotlin ; PHP and C# have them without an import, Go names them `am.GetAll`. `g.sys.system.executeQuery` calls the [execute plain query system API](https://docs.apimaker.dev/v4/docs/apis-all/system-apis/system-generated-execute-plain-query-api.html) from your code, whatever the settings of that API say about HTTP callers. ### Execute query System API Execute database query using global object 'g'. **TypeScript** ```typescript await g.sys.system.executeQuery({ instance: 'INSTANCE_NAME', database: 'DATABASE_NAME', collection: 'COLLECTION_NAME', query: "select * from DATABASE_NAME.COLLECTION_NAME" }); ``` - If the database is Mongodb API Maker supports all the commands listed in below. - https://www.mongodb.com/docs/drivers/node/current/usage-examples/command/ - https://www.mongodb.com/docs/v6.0/reference/command/ **TypeScript** ```typescript await g.sys.system.executeQuery({ instance: 'INSTANCE_NAME', database: 'DATABASE_NAME', query: { dbStats: 1, } }); ``` ## How we use Native Query in API Maker. ### Native query using secret management - Set Database constrain in Secret management. ```ts import * as T from 'types'; let Secret: T.ISecretType | any = { // Place your keys here in json format. common: { dbConstrain: { instance: 'mysql', database: 'inventory', collection: 'employees' } } }; module.exports = Secret; ``` - Read it from the secret, and create the table it names. **TypeScript** ```typescript const dbConstrain = await g.sys.system.getSecret('common.dbConstrain'); const instance = dbConstrain?.instance ?? 'mysql'; const database = dbConstrain?.database ?? 'inventory'; const collection = dbConstrain?.collection ?? 'employees'; await g.sys.system.executeQuery({ instance, query: `CREATE TABLE ${database}.${collection}(emp_id int AUTO_INCREMENT PRIMARY KEY);` }); ``` ### Various types of Database & It`s Native Query In API Maker - MySQL | TiDB | Percona XtraDB **TypeScript** ```typescript await g.sys.system.executeQuery({ instance: "mysql", query: "SELECT * FROM inventory.employees;" }); ``` - MariaDB **TypeScript** ```typescript await g.sys.system.executeQuery({ instance: "mariadb", query: "SELECT * FROM inventory.employees;" }); ``` - Microsoft SQL Server **TypeScript** ```typescript await g.sys.system.executeQuery({ instance: "sqlserver", query: "SELECT * FROM inventory.dbo.employees;" }); ``` - MongoDB **TypeScript** ```typescript await g.sys.system.executeQuery({ instance: 'mongodb', database: 'inventory', query: { dbStats: 1, } }); ``` - PostgreSQL **TypeScript** ```typescript await g.sys.system.executeQuery({ instance: "postgresql", query: `drop database if exists e_commerce;` }); await g.sys.system.executeQuery({ instance: "postgresql", query: `create database e_commerce;` }); await g.sys.system.executeQuery({ instance: "postgresql", database: "e_commerce", // 👈 Need to provide db name query: ` DROP TABLE IF EXISTS "public"."customers"; CREATE TABLE "public"."customers" ( "customer_id" int2 NOT NULL GENERATED BY DEFAULT AS IDENTITY ( INCREMENT 1 MINVALUE 1 MAXVALUE 32767 START 1 ), "first_name" varchar(45) COLLATE "pg_catalog"."default" NOT NULL, "last_name" varchar(45) COLLATE "pg_catalog"."default" NOT NULL, "phone" int8 NOT NULL, "last_update" timestamp(6) NOT NULL, "pincode" int NOT NULL, "shipping_id" int NULL, CONSTRAINT "customers_pkey" PRIMARY KEY ("customer_id") ); CREATE INDEX "idx_actor_last_name" ON "public"."customers" USING btree ("last_name" COLLATE "pg_catalog"."default" "pg_catalog"."text_ops" ASC NULLS LAST); INSERT INTO "public"."customers" ("first_name", "last_name", "phone", "last_update", "pincode", "shipping_id") VALUES ('PENELOPE', 'GUINESS', 123456789, '2006-02-15 04:34:33', 100050, 1); INSERT INTO "public"."customers" ("first_name", "last_name", "phone", "last_update", "pincode", "shipping_id") VALUES ('NICK', 'WAHLBERG', 1123456789, '2006-02-15 04:34:33', 111111, 2); INSERT INTO "public"."customers" ("first_name", "last_name", "phone", "last_update", "pincode", "shipping_id") VALUES ('ED', 'CHASE', 2123456789, '2006-02-15 04:34:33', 222222, 3); ` }); ``` - Oracle > Do not add a **semicolon (;)** at the end of a query or a statement of Oracle. **TypeScript** ```typescript await g.sys.system.executeQuery({ instance: "oracle", query: `SELECT * FROM "INVENTORY"."employees"` }); ``` ### DDL Operation in API Maker - CREATE TABLE **TypeScript** ```typescript await g.sys.system.executeQuery({ instance: "mysql", query: "CREATE TABLE inventory.employees(id int AUTO_INCREMENT PRIMARY KEY);" }) ``` - ALTER TABLE **TypeScript** ```typescript await g.sys.system.executeQuery({ instance: "mysql", query: "ALTER TABLE inventory.employees ADD COLUMN emp_name VARCHAR(30) NOT NULL;" }) ``` - RENAME TABLE **TypeScript** ```typescript await g.sys.system.executeQuery({ instance: "mysql", query: "ALTER TABLE inventory.employees RENAME COLUMN id TO emp_id;" }) ``` - TRUNCATE TABLE **TypeScript** ```typescript await g.sys.system.executeQuery({ instance: "mysql", query: "TRUNCATE TABLE inventory.employees;" }) ``` - DROP TABLE **TypeScript** ```typescript await g.sys.system.executeQuery({ instance: "mysql", query: "DROP TABLE IF EXISTS inventory.employees;" }) ``` ### DML Operation in API Maker API Maker allows us to perform various DML operations, such as the following examples. - INSERT **TypeScript** ```typescript await g.sys.system.executeQuery({ instance: "mysql", query: "INSERT into inventory.employees Values(101, 'Bob', 'M');" }) ``` - DELETE **TypeScript** ```typescript await g.sys.system.executeQuery({ instance: "mysql", query: "DELETE FROM inventory.employees WHERE emp_Id = '101';" }) ``` - UPDATE **TypeScript** ```typescript await g.sys.system.executeQuery({ instance: "mysql", query: "UPDATE inventory.employees SET emp_Name = 'Alice' WHERE emp_Id = '101';" }) ``` ### DQL Operation in API Maker API Maker allows us to perform various DQL operations, such as the following examples. - SELECT **TypeScript** ```typescript await g.sys.system.executeQuery({ instance: "mysql", query: "SELECT * FROM inventory.employees;" }) ``` - DISTINCT **TypeScript** ```typescript await g.sys.system.executeQuery({ instance: "mysql", query: "SELECT DISTINCT emp_Name FROM inventory.employees;" }) ``` - ORDER BY **TypeScript** ```typescript await g.sys.system.executeQuery({ instance: "mysql", query: "SELECT * FROM inventory.employees order by emp_Gen,emp_Name;" }) ``` ### Aggregated Function in API Maker API Maker allows us to perform various Aggregated Function, such as the following examples. - SUM **TypeScript** ```typescript await g.sys.system.executeQuery({ instance: "mysql", query: "SELECT SUM(emp_Sal) as Total_Salary FROM inventory.employees;" }) ``` - AVG **TypeScript** ```typescript await g.sys.system.executeQuery({ instance: "mysql", query: "SELECT AVG(emp_Sal) as Average_Salary FROM inventory.employees;" }) ``` ### Joins in API Maker API Maker allows us to perform Joins, such as the following examples. - INNER JOIN **TypeScript** ```typescript await g.sys.system.executeQuery({ instance: "mysql", query: "SELECT * FROM inventory.employees INNER JOIN inventory.attandance ON inventory.employees.emp_Id = inventory.attandance.emp_id;" }) ``` - LEFT JOIN **TypeScript** ```typescript await g.sys.system.executeQuery({ instance: "mysql", query: "SELECT * FROM inventory.employees LEFT JOIN inventory.attandance ON inventory.employees.emp_Id = inventory.attandance.emp_id;" }) ``` ### How to call SQL Server Store Procedure - Just replace your procedure name with below "procedureName". **TypeScript** ```typescript await g.sys.system.executeQuery({ instance: "sql_server", query: "USE inventory; exec dbo.procedureName;" }); ``` ### Commands of MongoDB : indexes A command of MongoDB is an object : `listIndexes`, `createIndexes`, `dropIndexes`… [createIndexes](https://docs.apimaker.dev/v4/docs/apis-all/system-apis/system-generated-create-indexes-api.html#from-code) and [getIndexes](https://docs.apimaker.dev/v4/docs/apis-all/system-apis/system-generated-get-indexes-api.html#from-code) do the same on every database, in the same words. **TypeScript** ```typescript const listed = await g.sys.system.executeQuery({ instance: 'mongodb', database: 'shop', query: { listIndexes: 'products' }, }); await g.sys.system.executeQuery({ instance: 'mongodb', database: 'shop', query: { createIndexes: 'products', indexes: [{ key: { category: 1, productName: 1 }, name: 'category_productName', unique: true }], }, }); ``` ## Multi-tenant - `instance: "crm::acme"` runs the query in the database of the tenant `acme` of the [multi-tenant](https://docs.apimaker.dev/v4/docs/features/multi-tenant.html) instance `crm`. - In a custom API called for a tenant, `instance: "crm"` runs it in the database of that tenant: the [x-am-tenant-username](https://docs.apimaker.dev/v4/docs/apis-all/header/requestHeader.html#x-am-tenant-username) header is passed on. Without a tenant, it runs in the structure database. **TypeScript** ```typescript // The database of acme. const ordersOfAcme = await g.sys.system.executeQuery({ instance: 'crm::acme', database: 'crm', query: "select status, count(*) as orders from orders group by status" }); // The database of the tenant of the request. const customers = await g.sys.system.executeQuery({ instance: 'crm', database: 'crm', query: "select count(*) as customers from customers" }); ``` ## Related - [Execute plain query system API](https://docs.apimaker.dev/v4/docs/apis-all/system-apis/system-generated-execute-plain-query-api.html) · [All system APIs from code](https://docs.apimaker.dev/v4/examples/sys/system/system.html) · [The global object g](https://docs.apimaker.dev/v4/docs/pre-defined-terms/global-object-g.html) (The code of this page is also written in Python, PHP, C#, Go, Rust, Java, Kotlin : https://docs.apimaker.dev/v4/examples/sys/system/executeQuery.md) --- # Call External API Example > Examples of calling other APIs from API Maker code - JSON, forms, file uploads, SOAP and XML, OAuth 2, retries, redirects, file downloads, and lists of calls in parallel or in sequence, in every language. Source: https://docs.apimaker.dev/v4/examples/sys/system/callExternalApi.html > **The code in every language** > > Each example is the inside of `main`, written in every [language](https://docs.apimaker.dev/v4/docs/languages/index.html) API Maker runs : pick yours in the tabs, and every page shows it from then on. The types a call takes (`GetAll`, `DeepItem`…) are those of `am` : `from am import GetAll` in Python, `use am::GetAll;` in Rust, `import am.GetAll;` in Java and Kotlin ; PHP and C# have them without an import, Go names them `am.GetAll`. `g.sys.system.callExternalApi` calls the [call external API system API](https://docs.apimaker.dev/v4/docs/apis-all/system-apis/system-generated-call-external-api.html) from your code, whatever the settings of that API say about HTTP callers. Call external API using global object 'g'. ### Simple call external apis **TypeScript** ```typescript await g.sys.system.callExternalApi([ { "url": `your_url`, "method": "GET", "timeout": 5000, "queryParams": { "select": "first_name" }, "headers": { "x-am-authorization": "TOKEN" }, } ]); ``` ### Parallel type - If the type is 'parallel' the external APIs are executed in parallel. **TypeScript** ```typescript await g.sys.system.callExternalApi([ { url: "FULL_URL", method: "POST", body: [ { first_name: "James", last_name: "Bond" } ], id: "saveApi", postProcess: [ { from: "saveApi.output.body.data.first_name", to: "setApi.body.first_name" } ], queryParams: { // the query params of a URL are texts : deep is its JSON deep: '[{"s_key":"SOURCE_COLLECTION_COLUMN_NAME","t_key":"TARGET_COLLECTION_COLUMN_NAME","t_col":"TARGET_COLLECTION_NAME","select":"COLUMN_NAMES"}]', select: "COLUMN_NAMES", limit: 2, sort: "COLUMN_NAMES" }, timeout: 1000, headers: { "x-am-authorization": "TOKEN" }, }, { type: 'parallel', data: [ { url: "FULL_URL", method: 'PUT', body: {}, id: "setApi", headers: { "x-am-authorization": "TOKEN" } }, { url: "FULL_URL", method: 'GET', headers: { "x-am-authorization": "TOKEN" } } ] } ]); ``` ### Sequential type - If the type is 'sequential' the API calls execute one by one. **TypeScript** ```typescript await g.sys.system.callExternalApi([ { url: "your_url", method: "GET", timeout: 5000, queryParams: { "select": "first_name" }, headers: { "x-am-meta": true }, id: "getData", output: "any" }, { type: "sequential", data: [ { url: "your_url", method: "POST", body: {}, id: "addData", preProcess: [ { from: "getData.output.body.data", to: "addData.body" } ], headers: { "x-am-authorization": "TOKEN", "x-am-response-case": "capitalCase" } }, { url: "your_url", method: "GET", headers: { "x-am-response-case": "capitalCase" } } ] } ]); ``` ### Path and query parameters, an API key, a form - `pathParams` fills `:customerId` of the URL, `queryArrayFormat: 'repeat'` writes the list as `tags=web&tags=priority`, and `bodyType: 'form'` sends the body as `product=Pen&quantity=3`. - `throwOnError` throws when the API answers with a status of 400 or above. **TypeScript** ```typescript const order = await g.sys.system.callExternalApi({ url: 'https://api.example.com/customers/:customerId/orders', method: 'POST', pathParams: { customerId: 42 }, queryParams: { tags: ['web', 'priority'] }, queryArrayFormat: 'repeat', auth: { type: 'apiKey', name: 'x-api-key', value: 'API_KEY' }, bodyType: 'form', body: { product: 'Pen', quantity: 3 }, throwOnError: true, }); g.logger.log(order.body.id); ``` ### Upload files - `bodyType: 'multipart'` sends a form of several parts : every key of the body is a field, and `{ file }` a file of the uploads folder. - A file a form sent to your custom API is sent on as it is : `document: g.req.files.files[0]`. **TypeScript** ```typescript await g.sys.system.callExternalApi({ url: 'https://api.example.com/documents', method: 'POST', auth: { type: 'bearer', token: 'TOKEN' }, bodyType: 'multipart', body: { title: 'Contract', // a file of the uploads folder document: { file: 'contracts/42.pdf' }, // a text sent as a file note: { content: 'Signed on site', fileName: 'note.txt' }, }, }); ``` ### XML and SOAP - `bodyType: 'xml'` sends the text of the body as it is, `responseType: 'text'` gives the answer as its text, whatever it holds. - `retry` sends the request again when it got no answer, or one of the statuses 408, 429, 500, 502, 503 and 504. **TypeScript** ```typescript const rate = await g.sys.system.callExternalApi({ url: 'https://soap.example.com/service', method: 'POST', bodyType: 'xml', headers: { 'content-type': 'text/xml; charset=utf-8', SOAPAction: 'urn:GetRate' }, body: "", responseType: 'text', retry: { count: 3, delay: 500 }, }); g.logger.log(rate.statusCode); ``` ### OAuth 2, redirects and retries - The token is asked of `tokenUrl` with the id and the secret of the client, kept until it expires, and asked for again when the API refuses it. - `ok` is `true` when the status of the answer is 200 to 299. **TypeScript** ```typescript const reports = await g.sys.system.callExternalApi({ url: 'https://api.example.com/reports', auth: { type: 'oauth2', tokenUrl: 'https://login.example.com/oauth/token', clientId: 'CLIENT_ID', clientSecret: 'CLIENT_SECRET', scope: 'reports.read', }, followRedirects: true, retry: 3, timeout: 10000, }); if (!reports.ok) g.logger.log(reports.statusCode); ``` ### Download a file - `download` saves the body of the answer as a file of the uploads folder, and the answer has `file` : its `path` in the uploads folder, its `name`, its `size` and its `contentType`. - Your code reads the file at `uploads/` + `file.path`. A custom API sends it to its caller by returning `{ __am__downloadFilePath: saved.file.path }`. - Redirects are followed. When the status of the answer is not 200 to 299 there is no `file` : the answer is given as any other. **TypeScript** ```typescript const saved = await g.sys.system.callExternalApi({ url: 'https://api.example.com/invoices/42/pdf', download: { path: 'invoices/42.pdf', fileName: 'Invoice 42.pdf' }, }); g.logger.log(saved.file.size); ``` ### Bytes - `responseType: 'base64'` gives the bytes of the answer as Base64 text, in every language. `'buffer'` gives a `Buffer` in TypeScript. - `bodyType: 'binary'` sends bytes : their Base64 text, a `Buffer`, or `{ file }` for a file of the uploads folder. **TypeScript** ```typescript const picture = await g.sys.system.callExternalApi({ url: 'https://api.example.com/logo.png', responseType: 'base64' }); await g.sys.system.callExternalApi({ url: 'https://storage.example.com/bucket/logo.png', method: 'PUT', bodyType: 'binary', headers: { 'content-type': 'image/png' }, body: picture.body, }); ``` ### A call which may fail - `allowFailure` : when the call fails, its answer is `{ statusCode: 0, ok: false, error: { message } }`, and the calls after it run. - `throwOnError` : a status of 400 or above ends the list with an error. `retry: 2` sends the request two more times first. **TypeScript** ```typescript await g.sys.system.callExternalApi([ { id: "audit", url: "https://audit.example.com/events", method: "POST", body: { event: "order" }, timeout: 2000, allowFailure: true }, { id: "order", url: "https://api.example.com/orders", method: "POST", body: { product: "Pen" }, retry: 2, throwOnError: true } ]); ``` ## Related - [Call external api system API](https://docs.apimaker.dev/v4/docs/apis-all/system-apis/system-generated-call-external-api.html) · [All system APIs from code](https://docs.apimaker.dev/v4/examples/sys/system/system.html) · [The global object g](https://docs.apimaker.dev/v4/docs/pre-defined-terms/global-object-g.html) (The code of this page is also written in Python, PHP, C#, Go, Rust, Java, Kotlin : https://docs.apimaker.dev/v4/examples/sys/system/callExternalApi.md) --- # Custom API Example > Learn how to create and implement custom APIs in API Maker with this comprehensive example, including code snippets and best practices. Source: https://docs.apimaker.dev/v4/examples/custom-apis/custom-api.html > **The code in every language** > > Each example is the inside of `main`, written in every [language](https://docs.apimaker.dev/v4/docs/languages/index.html) API Maker runs : pick yours in the tabs, and every page shows it from then on. The types a call takes (`GetAll`, `DeepItem`…) are those of `am` : `from am import GetAll` in Python, `use am::GetAll;` in Rust, `import am.GetAll;` in Java and Kotlin ; PHP and C# have them without an import, Go names them `am.GetAll`. The code of a [custom API](https://docs.apimaker.dev/v4/docs/apis-all/custom-apis/user-created-custom-api.html) : what to return, how to call the APIs of API Maker, how to send files. ## Basic code - A custom API is the function `main` of its language : what it returns is the `data` of the answer. The pieces below are the inside of `main`. **TypeScript** ```typescript return { hello: 'world' }; ``` ## Calls of `g.sys` - In TypeScript every `g.sys` call returns a promise : `await` it. A call without `await` runs, but its result and its errors are lost. The same in Python (in `async def main`) and C#. PHP, Go, Rust, Java and Kotlin wait for the answer of each call. **TypeScript** ```typescript return await g.sys.db.getAll({ instance: "INSTANCE_NAME", database: 'DB_NAME', collection: "COLLECTION_NAME", }); ``` ## The whole envelope : `true`, or `full` - A `g.sys` call returns the data and **throws** the errors of the API. - With `true` as the second argument in TypeScript, or through `full` in the other languages (`g.sys.db.full`, `g.Sys.Db.Full`), it returns the whole envelope `{ success, statusCode, data, errors, warnings }` and never throws : read `success` yourself. **TypeScript** ```typescript let saveData = await g.sys.db.saveSingleOrMultiple({ instance: "INSTANCE_NAME", database: 'DB_NAME', collection: "COLLECTION_NAME", saveData: {}, headers: {} }, true); let countOfAllData = await g.sys.db.count({ instance: "INSTANCE_NAME", database: 'DB_NAME', collection: "COLLECTION_NAME", }, true); return { saveData, countOfAllData }; ``` ## Throw an error - An error raised ends the call with `success: false`, the message in `errors` and its code as the status. A message listed in the `errorList` of the API can be [translated](https://docs.apimaker.dev/v4/docs/i18/i18.html). **TypeScript** ```typescript let saveData = await g.sys.db.saveSingleOrMultiple({ instance: "INSTANCE_NAME", database: 'DB_NAME', collection: "COLLECTION_NAME", saveData: {}, headers: {} }, true); if (!saveData.success) throw [{ code: T.EStatusCode.BAD_REQUEST, message: 'Your data is not saved!' }]; return saveData; ``` ## Return an image or any binary - Set `g.res.contentType` and return the base64 of the content. **TypeScript** ```typescript g.res.contentType = 'image/gif' as T.EContentType; return `data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOwA=` ``` ## Download file **TypeScript** ```typescript import * as T from 'types'; import * as fs from 'fs'; import * as path from 'path'; async function main(g: T.IAMGlobal) { // always write file in the uploads folder which you want to send to user. // you can write other files in any directory which you don't want to send to user. await fs.promises.mkdir(path.join(__dirname, 'uploads'), { recursive: true }); let filePath = path.join(__dirname, 'uploads', 'myfile.txt'); await fs.promises.writeFile(filePath, 'file 1 content', { encoding: 'utf8' }); return { // just provide file name which is written to "uploads" directory __am__downloadFilePath: 'myfile.txt', __am__downloadFolderFileName: 'newName.txt', // download file will have this name. } }; module.exports = main; ``` **TypeScript** ```typescript import * as T from 'types'; import * as fs from 'fs'; import * as path from 'path'; async function main(g: T.IAMGlobal) { return { __am__downloadFileOrFolderPaths: [ { fsSource: path.join('folder1', 'folder2', 'folder3', 'data_folder'), // path into uploads folder archiveDestination: 'data_folder', // path in zip file, so data_folder folder will be directly available in zip file. }, ], __am__downloadFolderFileName: `output.zip`, // download file will have this name. } }; module.exports = main; ``` ## Download files & folders **TypeScript** ```typescript import * as T from 'types'; import * as fs from 'fs'; import * as path from 'path'; async function main(g: T.IAMGlobal) { // always write file in the uploads folder which you want to send to user. // you can write other files in any directory which you don't want to send to user. await fs.promises.mkdir(path.join(__dirname, 'uploads'), { recursive: true }); let filePath = path.join(__dirname, 'uploads', 'myfile.txt'); await fs.promises.writeFile(filePath, 'file 1 content', { encoding: 'utf8' }); return { // You can provide list of files or folders, it will will make zip and send to user. __am__downloadFileOrFolderPaths: [ 'myfile.txt', // file name 'someFolder', // folder name ], __am__downloadFolderFileName: 'zipFile.zip', // this will be zip file name } }; module.exports = main; ``` ## Download file from Angular sent by custom API ```ts async function downloadFileFromBrowser() { const requestPayload = {}; const requestHeaders = {}; const resp = await this.http.post(`API Maker custom API endpoint`, requestPayload, { headers: requestHeaders, responseType: 'text', observe: 'response', }).toPromise(); const fileName = resp.headers.get('content-filename'); await this.downloadFileFromBlob('application/zip', resp.body, fileName); return resp; } async function downloadFileFromBlob(contentType, base64Data: any, fileName) { const a = document.createElement('a'); document.body.appendChild(a); a.style.display = 'none'; let blob; if (base64Data instanceof Blob) { blob = base64Data; } else { const base64Response = await fetch(`data:${contentType};base64,` + base64Data); blob = await base64Response.blob(); } const url = window.URL.createObjectURL(blob); a.href = url; a.download = fileName; a.click(); window.URL.revokeObjectURL(url); } ``` ## Multi-tenant - Call a custom API with the [x-am-tenant-username](https://docs.apimaker.dev/v4/docs/apis-all/header/requestHeader.html#x-am-tenant-username) header to run it for one tenant of a [multi-tenant](https://docs.apimaker.dev/v4/docs/features/multi-tenant.html) instance. - It reads the tenant in `g.req.params`, and the APIs it calls with `g.sys.db` and `g.sys.system` work on the database of that tenant: the header is passed on, and each instance finds the tenant in its own tenants table. - `instance: 'crm::globex'` names another tenant for one call, and an empty tenant header names the structure database. See [Custom APIs of a multi-tenant instance](https://docs.apimaker.dev/v4/docs/features/multi-tenant.html#custom-apis). ```text GET /api/custom-api/admin/customers-report x-am-tenant-username: acme ``` **TypeScript** ```typescript import * as T from 'types'; async function main(g: T.IAMGlobal) { const tenant = g.req.params.tenantUsername; // 'acme' const customers = await g.sys.db.getAll({ instance: 'crm', database: 'crm', collection: 'customers' }); // from the database of acme const customersOfGlobex = await g.sys.db.count({ instance: 'crm::globex', database: 'crm', collection: 'customers' }); return { tenant, customers, customersOfGlobex }; } module.exports = main; ``` (The code of this page is also written in Python, PHP, C#, Go, Rust, Java, Kotlin : https://docs.apimaker.dev/v4/examples/custom-apis/custom-api.md) --- # The Request in Code (g.req) > Read the request in your code with g.req of API Maker - its body, headers, params of the path, query params and the data of an event - with the same code in eight languages. Source: https://docs.apimaker.dev/v4/examples/req/req.html > **The code in every language** > > Each example is the inside of `main`, written in every [language](https://docs.apimaker.dev/v4/docs/languages/index.html) API Maker runs : pick yours in the tabs, and every page shows it from then on. The types a call takes (`GetAll`, `DeepItem`…) are those of `am` : `from am import GetAll` in Python, `use am::GetAll;` in Rust, `import am.GetAll;` in Java and Kotlin ; PHP and C# have them without an import, Go names them `am.GetAll`. Custom APIs, hooks, events and schedulers read the request through `g.req`. Who calls is in `g.req.auth` : see [Who calls : g.req.auth](https://docs.apimaker.dev/v4/examples/req/auth/auth.html). ## Body To get the value of request body, use `g.req.body`. **TypeScript** ```typescript const body = g.req.body; ``` ## Headers To get the value of requested headers, use `g.req.headers`. **TypeScript** ```typescript const headers = g.req.headers; ``` The [tenant header](https://docs.apimaker.dev/v4/docs/apis-all/header/requestHeader.html#x-am-tenant-username) of a request of a tenant of a [multi-tenant](https://docs.apimaker.dev/v4/docs/features/multi-tenant.html) instance. `g.req.params.tenantUsername` holds the tenant too, also when the request named it in the path (`crm::acme`). **TypeScript** ```typescript const tenantUsername = g.req.headers['x-am-tenant-username']; // 'acme' ``` ## Params To get the value of requested params, use `g.req.params`. **TypeScript** ```typescript const params = g.req.params; ``` The tenant of the request, for a [multi-tenant](https://docs.apimaker.dev/v4/docs/features/multi-tenant.html) instance: named with the [x-am-tenant-username](https://docs.apimaker.dev/v4/docs/apis-all/header/requestHeader.html#x-am-tenant-username) header, or in the path of an API of the instance (`crm::acme`). **TypeScript** ```typescript const tenantUsername = g.req.params.tenantUsername; // 'acme', undefined without a tenant ``` ## Query params To get the value of requested query params, use `g.req.query`. **TypeScript** ```typescript const query = g.req.query; ``` ## Event data To get the value of requested body data of the event, use `g.req.eventData`. **TypeScript** ```typescript const eventData = g.req.eventData; ``` ## Related - [The global object g](https://docs.apimaker.dev/v4/docs/pre-defined-terms/global-object-g.html) · [Custom APIs](https://docs.apimaker.dev/v4/docs/apis-all/custom-apis/user-created-custom-api.html) · [The answer : g.res](https://docs.apimaker.dev/v4/examples/res/res.html) (The code of this page is also written in Python, PHP, C#, Go, Rust, Java, Kotlin : https://docs.apimaker.dev/v4/examples/req/req.md) --- # Who Calls (g.req.auth) > Read in your code who calls an API of API Maker - the API user, a person of your users table, a person of Google, Azure AD or AWS Cognito - with g.req.auth, in eight languages, and a login API which gets both tokens. Source: https://docs.apimaker.dev/v4/examples/req/auth/auth.html > **The code in every language** > > Each example is the inside of `main`, written in every [language](https://docs.apimaker.dev/v4/docs/languages/index.html) API Maker runs : pick yours in the tabs, and every page shows it from then on. The types a call takes (`GetAll`, `DeepItem`…) are those of `am` : `from am import GetAll` in Python, `use am::GetAll;` in Rust, `import am.GetAll;` in Java and Kotlin ; PHP and C# have them without an import, Go names them `am.GetAll`. Every provider which checked a token of the call leaves what it found in `g.req.auth` : the application in `authAMUser`, the person in `authAMDB`, `authGoogle`, `authAzure`, `authAWS` or `authCustom`. The [sign-in providers](https://docs.apimaker.dev/v4/docs/authorization/sign-in-providers.html) page says how each one is set up. ## The API user The application behind `x-am-authorization`, from the [token API](https://docs.apimaker.dev/v4/docs/apis-all/system-apis/system-generated-token-api.html). **TypeScript** ```typescript const apiUserAuth = g.req.auth.authAMUser; // the API user of the token of x-am-authorization ``` ## A person of your users table The person behind `x-am-user-authorization`, a row of the table of a [DB token generator](https://docs.apimaker.dev/v4/docs/authorization/AMDB.html). **TypeScript** ```typescript const databaseUserAuth = g.req.auth.authAMDB; // the row of the person, without its password ``` ### A login API which gets both tokens **TypeScript** ```typescript import * as T from 'types'; // A login API (apiAccessType : IS_PUBLIC) : the token of the API user 'default' for the app, and the token of the // person whose email and password the body brings, checked by the DB token generator 'users_tg'. async function main(g: T.IAMGlobal) { const password = await g.sys.system.getSecret('common.apiUserPasswords.default'); const [app, person] = await g.sys.system.getToken([ { u: 'default', p: password }, { name: 'users_tg', u: g.req.body.email, p: g.req.body.password }, ]); return { amToken: app.token, amDbToken: person.token, refreshToken: person.refresh_token }; } module.exports = main; ``` - The token of a person, a row of the table of the token generator `users_tg`, from the [token API](https://docs.apimaker.dev/v4/docs/apis-all/system-apis/system-generated-token-api.html#the-token-of-a-person) : ```json { "name": "users_tg", "u": "USER_NAME", "p": "PASSWORD" } ``` ## Google, Azure AD and AWS Cognito The opened token of the provider, with the columns its `groupsDataSource` selected from your table. ### Google **TypeScript** ```typescript const googleAuth = g.req.auth.authGoogle; // the opened token of x-google-authorization ``` ### Azure AD **TypeScript** ```typescript const azureAuth = g.req.auth.authAzure; // the opened token of x-azure-authorization ``` ### AWS Cognito **TypeScript** ```typescript const awsAuth = g.req.auth.authAWS; // the opened token of x-aws-authorization ``` ## A provider of your own The result of your token validator, in `g.req.auth.authCustom` : see [the custom provider example](https://docs.apimaker.dev/v4/examples/req/auth/authCustom.html). ## Related - [Sign-in providers](https://docs.apimaker.dev/v4/docs/authorization/sign-in-providers.html) · [The request : g.req](https://docs.apimaker.dev/v4/examples/req/req.html) · [The global object g](https://docs.apimaker.dev/v4/docs/pre-defined-terms/global-object-g.html) (The code of this page is also written in Python, PHP, C#, Go, Rust, Java, Kotlin : https://docs.apimaker.dev/v4/examples/req/auth/auth.md) --- # Custom Auth Provider Example > Build your own token provider in API Maker with jose — sign it, validate it, and read the payload from g.req.auth.authCustom. Source: https://docs.apimaker.dev/v4/examples/req/auth/authCustom.html > **The code in every language** > > Each example is the inside of `main`, written in every [language](https://docs.apimaker.dev/v4/docs/languages/index.html) API Maker runs : pick yours in the tabs, and every page shows it from then on. The types a call takes (`GetAll`, `DeepItem`…) are those of `am` : `from am import GetAll` in Python, `use am::GetAll;` in Rust, `import am.GetAll;` in Java and Kotlin ; PHP and C# have them without an import, Go names them `am.GetAll`. ### Custom authorization To get the value of request header `x-custom-authorization`, use `g.req.auth.authCustom`. **TypeScript** ```typescript const customAuth = g.req.auth.authCustom; // what the token validator returned ``` Whatever your **Token Validator** function returns is what lands in `g.req.auth.authCustom`. Return the decoded JWT payload and you get the decoded token there — return your own object and you get that instead. ## Why a custom provider? AM, database, AWS, Azure and Google cover most cases. But sometimes the token is yours — your own claims, your own signing key, your own expiry rules. That is what a **Custom Token Generator** is for: you write the code that mints the token and the code that checks it, and API Maker handles the rest of the request pipeline. Below is a complete working example: a JWT signed with HS256, with the usual JWT package of each language. --- ### 1. Add a JWT package, and a signing key Go to **Operations → Sandbox Settings**, select the language of the provider and add its package (see [Packages](https://docs.apimaker.dev/v4/docs/settings/sandboxSettings.html#packages)): | Language | Registry | Package | |---|---|---| | TypeScript | npm | `jose` | | Python | PyPI | `pyjwt` | | PHP | Packagist | `firebase/php-jwt` | | C# | NuGet | `Microsoft.IdentityModel.JsonWebTokens` | | Go | Go modules | `github.com/golang-jwt/jwt/v5` | | Rust | crates.io | `jsonwebtoken[rust_crypto]` and `uuid[v4]` | | Java, Kotlin | Maven Central | `com.auth0:java-jwt` | Once added, it is available in every piece of code of that language, including the two functions below. Then add a key of your own to the [secret](https://docs.apimaker.dev/v4/docs/secrets/secrets.html#your-own-keys), `jwtSigningKey`, with at least 32 random characters: the packages of PHP and C# refuse a shorter key for HS256. Keep it for the tokens alone. `common.secretFETransfer` is no signing key: your apps hold it, so anyone with a copy of an app could sign tokens with it. --- ### 2. Create the auth provider Go to **Security → Auth Providers**, click **+** and pick **Custom Token Generator**. You will get three tabs: **Basic Info**, **Token Generator** and **Token Validator**. The Basic Info is always TypeScript, which API Maker [runs itself](https://docs.apimaker.dev/v4/docs/languages/index.html#settings-run) when you save ; the generator and the validator are written in the [language](https://docs.apimaker.dev/v4/docs/languages/index.html#basic-info) you pick for the provider. #### Basic Info ```ts import * as T from 'types'; let customTokenBasicInfo: Partial = { name: 'jose_example', runOnNativeProcess: false, }; module.exports = customTokenBasicInfo; ``` - `name` is how you will refer to this provider everywhere else — in the get-token request and in the `authProviders` array of your settings files. - Keep `runOnNativeProcess` as `false` so the code runs inside the sandbox, where the packages of its language live. #### Token Generator Runs when someone asks for a token. Whatever you return is sent back to the caller as-is. **TypeScript** **Token Generator** ```typescript import * as T from 'types'; import { SignJWT } from "jose"; // Produce and return a token string from the request context. // Runs at token-generation time. async function main(g: T.IAMGlobal) { const body: { role: string, userId: string } = g.req.body; const signingKey = await g.sys.system.getSecret('jwtSigningKey'); const secret = new TextEncoder().encode(signingKey); const accessToken = await new SignJWT({ // set your required data role: body.role, email: "ada@example.com", companyId: "cmp_123", }).setProtectedHeader({ alg: "HS256", typ: "JWT", }).setSubject(body.userId) .setIssuedAt() .setExpirationTime("15m") .setJti(crypto.randomUUID()) .sign(secret); return { access_token: accessToken, refresh_token: 'refresh_token_test', validity: 19200 }; }; module.exports = main; ``` The whole request body reaches this function as `g.req.body`, so you decide what your login payload looks like. #### Token Validator Runs on every request that carries the `x-custom-authorization` header. The token is in `g.req.body.token`. **TypeScript** **Token Validator** ```typescript import * as T from 'types'; import { jwtVerify } from "jose"; // Validate an incoming token. Return a truthy object (usually the decoded payload) to mark valid. // Throw or return null/undefined to mark invalid. async function main(g: T.IAMGlobal) { const accessToken = g.req.body.token; const signingKey = await g.sys.system.getSecret('jwtSigningKey'); const secret = new TextEncoder().encode(signingKey); const { payload } = await jwtVerify(accessToken, secret, { algorithms: ["HS256"], }); return payload; // return true; // if truthy value returned, means token is valid. // return false; // if token is not valid // return {}; // You can return some object also and it means token is valid. }; module.exports = main; ``` The rule is simple — **truthy means valid**. Anything falsy, or a thrown error, means the request is rejected. --- ### 3. Generate a token Request Method: POST URL ```text /api/system-api/user-path/token ``` ```json { "name": "jose_example", "userId": "user_123", "role": "admin" } ``` - `name` tells API Maker which auth provider to run. Everything else in the body is yours and is passed straight to your Token Generator as `g.req.body`. - For more information about this API [click here](https://docs.apimaker.dev/v4/docs/apis-all/system-apis/system-generated-token-api.html). Response — exactly what your generator returned: ```json { "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "refresh_token": "refresh_token_test", "validity": 19200 } ``` --- ### 4. Send the token Put the `access_token` in the `x-custom-authorization` header on every call: ```text x-custom-authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... ``` To let an API accept this provider, add its name to `authProviders` in your settings file: ```ts authProviders: ["jose_example"], ``` --- ### 5. Read it in your custom code **TypeScript** ```typescript import * as T from 'types'; async function main(g: T.IAMGlobal) { const auth = g.req.auth.authCustom; g.logger.log(auth.sub); // user_123 g.logger.log(auth.role); // admin g.logger.log(auth.companyId); // cmp_123 return { ok: true }; }; module.exports = main; ``` By the time your code runs, the token is already verified — API Maker rejects bad ones before they reach you. So `g.req.auth.authCustom` is safe to trust. ## Related - [The global object g](https://docs.apimaker.dev/v4/docs/pre-defined-terms/global-object-g.html) · [Custom APIs](https://docs.apimaker.dev/v4/docs/apis-all/custom-apis/user-created-custom-api.html) (The code of this page is also written in Python, PHP, C#, Go, Rust, Java, Kotlin : https://docs.apimaker.dev/v4/examples/req/auth/authCustom.md) --- # The Answer in Code (g.res) > Shape the answer of an API in your code with g.res of API Maker - its output, status code, errors, warnings, data shared between hooks, and the content type (JSON, HTML, text, XML, YAML, bytes) - in eight languages. Source: https://docs.apimaker.dev/v4/examples/res/res.html > **The code in every language** > > Each example is the inside of `main`, written in every [language](https://docs.apimaker.dev/v4/docs/languages/index.html) API Maker runs : pick yours in the tabs, and every page shows it from then on. The types a call takes (`GetAll`, `DeepItem`…) are those of `am` : `from am import GetAll` in Python, `use am::GetAll;` in Rust, `import am.GetAll;` in Java and Kotlin ; PHP and C# have them without an import, Go names them `am.GetAll`. Custom APIs and hooks shape the answer of the request through `g.res`. ## Output **TypeScript** ```typescript g.res.output = { hello: 'world' }; ``` Response ```json { "success": true, "statusCode": 200, "data": { "hello": "world" } } ``` ## Status code `statusCode` use to set/get status code of the response. **TypeScript** ```typescript g.res.statusCode = T.EStatusCode.BAD_REQUEST; ``` Response ```json { "success": false, "statusCode": 400, "data": 400 } ``` All supported status code. ```text OK = 200, NO_CONTENT = 204, CREATED = 201, BAD_REQUEST = 400, UNAUTHORIZED = 401, FORBIDDEN = 403, RESOURCE_NOT_FOUND = 404, INTERNAL_SERVER_ERROR = 500 ``` ## Errors **TypeScript** ```typescript g.res.errors = [{ code: 400, message: "Error message here." }]; ``` Response ```json { "success": false, "statusCode": 400, "errors": [ { "code": 400, "message": "Error message here." } ], "warnings": [] } ``` ## Warnings **TypeScript** ```typescript g.res.warnings = [{ code: 401, message: "This is warning!" }]; return { hello: 'v2' }; ``` Response ```json { "success": true, "statusCode": 200, "data": { "hello": "v2" }, "warnings": [ { "code": 401, "message": "This is warning!" } ] } ``` ## Shared between hooks and code `g.res.shared` is used to share data between post-hooks, pre-hooks, and code within that API. **TypeScript** ```typescript g.res.shared.name = 'Joe'; return g.res.shared.name; ``` Response ```json { "success": true, "statusCode": 200, "data": "Joe" } ``` ## Content types - The user does not need to set the response content type to send JSON as a response. - If the response content type is not set that means it is application/JSON. If ContentType is set to below system will return data accordingly. ```text JSON = 'application/json' XML = 'text/xml' YAML = 'text/yaml' TEXT = 'text/plain' HTML = 'text/html' ``` > Note: If content type is set and not from above list, then API Maker will consider a text the code returns as base64 encoded. Bytes the code returns (a `Buffer`, `bytes`, `byte[]`, `[]byte`…) are sent as they are, whatever the content type : see OCTET_STREAM below. ### HTML **TypeScript** **Content type HTML** ```typescript g.res.contentType = T.EContentType.HTML; return "

My First Heading

My first paragraph.

"; ``` Response ```html

My First Heading

My first paragraph.

``` ### JSON **TypeScript** **Content type JSON** ```typescript g.res.contentType = T.EContentType.JSON; g.res.errors = [{ code: 401, message: "This is error" }]; g.res.statusCode = 555; return "World"; ``` Response ```json { "success": false, "statusCode": 555, "data": "World", "errors": [ { "code": 401, "message": "This is error" } ], "warnings": [] } ``` ### Bytes : application/octet-stream **TypeScript** **Content type OCTET_STREAM** ```typescript g.res.contentType = T.EContentType.OCTET_STREAM; ``` - It will download the image. **TypeScript** **base64** ```typescript g.res.contentType = 'image/gif' as T.EContentType; return 'data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOwA='; ``` - It will send the bytes as they are : a file the code read or downloaded, a PDF it made. Return the bytes (a `Buffer`, `bytes`, `byte[]`, `[]byte`), or leave them in `g.res.output` : the answer is those bytes, under the content type the code names, whatever it is (`image/png`, `application/pdf`…). Headers of the code go with them (`Content-Disposition`, `Cache-Control`). **TypeScript** **bytes** ```typescript const picture = Buffer.from('R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOwA=', 'base64'); g.res.contentType = 'image/gif' as T.EContentType; g.res.headers = { 'Content-Disposition': 'inline; filename="pixel.gif"' }; return picture; ``` ### Text **TypeScript** **Content type TEXT** ```typescript g.res.contentType = T.EContentType.TEXT; return "Hello world from the API Maker."; ``` Response ```text Hello world from the API Maker. ``` ### XML **TypeScript** **Content type XML** ```typescript g.res.contentType = T.EContentType.XML; return "Hello world from the API Maker."; ``` Response ```xml true 200 Hello world from the API Maker. ``` ### YAML **TypeScript** **Content type YAML** ```typescript g.res.contentType = T.EContentType.YAML; return "Hello world from the API Maker."; ``` Response ```yaml success: true statusCode: 200 data: Hello world from the API Maker. ``` ## Related - [The global object g](https://docs.apimaker.dev/v4/docs/pre-defined-terms/global-object-g.html) · [Response format](https://docs.apimaker.dev/v4/docs/apis-all/response-format.html) · [The request : g.req](https://docs.apimaker.dev/v4/examples/req/req.html) (The code of this page is also written in Python, PHP, C#, Go, Rust, Java, Kotlin : https://docs.apimaker.dev/v4/examples/res/res.md) --- # Global Shared Example > See how to use g.shared to share data across APIs, pre/post-hooks, and custom code in API Maker—enable seamless data flow. Source: https://docs.apimaker.dev/v4/examples/shared/globalShared.html > **The code in every language** > > Each example is the inside of `main`, written in every [language](https://docs.apimaker.dev/v4/docs/languages/index.html) API Maker runs : pick yours in the tabs, and every page shows it from then on. The types a call takes (`GetAll`, `DeepItem`…) are those of `am` : `from am import GetAll` in Python, `use am::GetAll;` in Rust, `import am.GetAll;` in Java and Kotlin ; PHP and C# have them without an import, Go names them `am.GetAll`. ### Shared data globally `g.shared` is used to share data between post-hooks, pre-hooks, code, and APIs. - If the user set a shared variable from the one API response. **TypeScript** ```typescript g.shared.lastOutput = g.res.output; ``` - User can get that shared variables value in another API. **TypeScript** ```typescript const lastOutput = g.shared.lastOutput; ``` ## Related - [The global object g](https://docs.apimaker.dev/v4/docs/pre-defined-terms/global-object-g.html) · [Custom APIs](https://docs.apimaker.dev/v4/docs/apis-all/custom-apis/user-created-custom-api.html) (The code of this page is also written in Python, PHP, C#, Go, Rust, Java, Kotlin : https://docs.apimaker.dev/v4/examples/shared/globalShared.md)