# System APIs Examples

> Explore practical examples of API Maker's system APIs, including encryption, hashing, token generation, external API calls, Redis operations, and more.

Source: https://docs.apimaker.dev/v1/examples/sys/system/system.html

## Encrypt data

`g.sys.system.encrypt` calls the [encrypt data system API](https://docs.apimaker.dev/v1/docs/apis-all/system-apis/system-generated-encrypt-data-api.html) from your code, whatever the settings of that API say about HTTP callers.

### Encrypt System API

Get encrypted data using global object 'g'.
```ts
let encryptedData = await g.sys.system.encrypt({
    "data": {
        "name": "Bob"
    }
});
```

## Decrypt data

`g.sys.system.decrypt` calls the [decrypt data system API](https://docs.apimaker.dev/v1/docs/apis-all/system-apis/system-generated-decrypt-data-api.html) from your code, whatever the settings of that API say about HTTP callers.

### Decrypt System API

Get decrypted data using global object 'g'.
```ts
let decryptedData = await g.sys.system.decrypt("U2FsdGVkX191c+lmyM80ctf4QV18dZ/x17yDh/fRxs4=");
```

## Hash data

`g.sys.system.hash` calls the [hash data system API](https://docs.apimaker.dev/v1/docs/apis-all/system-apis/system-generated-hash-data-api.html) from your code, whatever the settings of that API say about HTTP callers.

### Hash System API

Get hash of the given data using the global object 'g'.
```ts
let hashData = await g.sys.system.hash({ "Name": "Alice" });
```

## Get token

`g.sys.system.getToken` calls the [get token system API](https://docs.apimaker.dev/v1/docs/apis-all/system-apis/system-generated-token-api.html) from your code, whatever the settings of that API say about HTTP callers.

### Get token using global object 'g'.

- Token of an API Maker API user: no `name`.

```ts
await g.sys.system.getToken({
    "u": "USER_NAME",
    "p": "USER_PASSWORD"
});
```

- Token of a database user (application user): the `name` of its token generator.

```ts
await g.sys.system.getToken({
    "name": "TOKEN_GENERATOR_NAME",
    "u": "USER_NAME",
    "p": "PASSWORD"
});
```

- Both at once: an array in, an array of tokens out.

```ts
const [apiUser, databaseUser] = await g.sys.system.getToken([
    { "u": "USER_NAME", "p": "USER_PASSWORD" },
    { "name": "TOKEN_GENERATOR_NAME", "u": "USER_NAME", "p": "PASSWORD" }
]);
// apiUser.token goes in x-am-authorization, databaseUser.token in x-am-user-authorization
```

## Execute query

`g.sys.system.executeQuery` calls the [execute plain query system API](https://docs.apimaker.dev/v1/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'.

```ts
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/

```ts
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: <T.ISecretTypeCommon>{
        dbConstrain: {
            instance: 'mysql',
            database: 'inventory',
            collection: ''
        }
    }
};
module.exports = Secret;
```

- Get Database constrain from Secret management.
```ts
let dbConstrain = await g.sys.system.getSecret('common.dbConstrain');
let instance = dbConstrain.instance || 'mysql';
let database = dbConstrain.database || 'inventory';
let collection = dbConstrain.collection || 'employees';
```

- Create table
```ts
await g.sys.system.executeQuery({
    instance: `${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
```ts
await g.sys.system.executeQuery({
    instance: "mysql",
    query: "SELECT * FROM inventory.employees;"
});
```

- MariaDB
```ts
await g.sys.system.executeQuery({
    instance: "mariadb",
    query: "SELECT * FROM inventory.employees;"
});
```

- Microsoft SQL Server
```ts
await g.sys.system.executeQuery({
    instance: "sqlserver",
    query: "SELECT * FROM inventory.dbo.employees;"
});
```

- MongoDB
```ts
await g.sys.system.executeQuery({
    instance: 'mongodb',
    database: 'inventory',
    query: {
        dbStats: 1,
    }
});
```

- PostgreSQL
```ts
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

> Please follow these rules when writing a query or statement:

> - Use **backticks (`)** to enclose your query or statement.
> - Do not add a **semicolon (;)** at the end of your query.

```ts
await g.sys.system.executeQuery({
    instance: "oracle",
    query: `SELECT * FROM "INVENTORY"."employees"`
});
```

### DDL Operation in API Maker

- CREATE TABLE
```ts
await g.sys.system.executeQuery({
    instance: "mysql",
    query: "CREATE TABLE inventory.employees(id int AUTO_INCREMENT PRIMARY KEY);"
})
```

- ALTER TABLE
```ts
await g.sys.system.executeQuery({
    instance: "mysql",
    query: "ALTER TABLE inventory.employees ADD COLUMN emp_name VARCHAR(30) NOT NULL;"
})
```

- RENAME TABLE
```ts
await g.sys.system.executeQuery({
    instance: "mysql",
    query: "ALTER TABLE inventory.employees RENAME COLUMN id TO emp_id;"
})
```

- TRUNCATE TABLE
```ts
await g.sys.system.executeQuery({
    instance: "mysql",
    query: "TRUNCATE TABLE inventory.employees;"
})
```

- DROP TABLE
```ts
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
```ts
await g.sys.system.executeQuery({
    instance: "mysql",
    query: "INSERT into inventory.employees Values(101, 'Bob', 'M');"
})
```

- DELETE
```ts
await g.sys.system.executeQuery({
    instance: "mysql",
    query: "DELETE FROM inventory.employees WHERE emp_Id = '101';"
})
```

- UPDATE
```ts
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
```ts
await g.sys.system.executeQuery({
    instance: "mysql",
    query: "SELECT * FROM inventory.employees;"
})
```

- DISTINCT
```ts
await g.sys.system.executeQuery({
    instance: "mysql",
    query: "SELECT DISTINCT emp_Name FROM inventory.employees;"
})
```

- ORDER BY
```ts
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
```ts
await g.sys.system.executeQuery({
    instance: "mysql",
    query: "SELECT SUM(emp_Sal) as Total_Salary FROM inventory.employees;"
})
```

- AVG
```ts
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
```ts
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
```ts
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".
```ts
await g.sys.system.executeQuery({
    instance: "sql_server",
    query: "USE inventory; exec dbo.procedureName;"
});
```

### How to create index in Mongodb

```ts
import * as T from 'types';
import * as db from 'db-interfaces';
import * as C from 'iot/Constants';

const createIndexList: IIndexObj[] = [{
    collectionName: "collectionName",
    indexName: 'indexName',
    isUnique: true,
    fields: {
        "category": 1,
        "productName": 1,
    },
}];

async function main(g: T.IAMGlobal) {
    const colMap = {};
    for (const iObj of createIndexList) {
        await dropIndexListOfCollection(g, iObj.collectionName, iObj.indexName);
        await createIndexOnCollection(g, iObj.collectionName, iObj.fields, iObj.indexName, iObj.isUnique);
        colMap[iObj.collectionName] = 1;
    }

    for (const colName in colMap) {
        const indexList = await getIndexListOfCollection(g, C.col.configuration_transactions);
        colMap[colName] = indexList;
    }

    return { hello: 'world', colMap };
};
module.exports = main;


async function getIndexListOfCollection(
    g: T.IAMGlobal,
    collectionName: string,
) {
    const listIndexResp = await g.sys.system.executeQuery({
        instance: C.insDB.instance,
        database: C.insDB.database,
        query: {
            listIndexes: collectionName,
        }
    });

    const indexList = [];
    for (const item of listIndexResp?.cursor?.firstBatch || []) {
        indexList.push(item.name);
    }

    return indexList;
}

async function createIndexOnCollection(
    g: T.IAMGlobal,
    collectionName: string,
    fields: any,
    indexName: string,
    isUnique: boolean,
) {
    const createIndexResp = await g.sys.system.executeQuery({
        instance: C.insDB.instance,
        database: C.insDB.database,
        query: {
            createIndexes: collectionName,
            indexes: [
                {
                    key: fields,
                    name: indexName,
                    unique: isUnique,
                },
            ],
        }
    });

    const indexList = [];
    for (const item of createIndexResp?.cursor?.firstBatch || []) {
        indexList.push(item.name);
    }

    return indexList;
}

async function dropIndexListOfCollection(
    g: T.IAMGlobal,
    collectionName: string,
    indexName: string,
) {
    try {
        const dropResp = await g.sys.system.executeQuery({
            instance: C.insDB.instance,
            database: C.insDB.database,
            query: {
                dropIndexes: collectionName,
                index: indexName,
            }
        });
        return dropResp;
    } catch (e) {
    }
}


interface IIndexObj {
    indexName: string;
    collectionName: string;
    fields: any;
    isUnique: boolean;
}
```

## Multi-tenant

- `instance: "crm::acme"` runs the query in the database of the tenant `acme` of the [multi-tenant](https://docs.apimaker.dev/v1/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/v1/docs/apis-all/header/requestHeader.html#x-am-tenant-username) header is passed on. Without a tenant, it runs in the structure database.

```ts
// 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"
});
```

## Call external API

`g.sys.system.callExternalApi` calls the [call external API system API](https://docs.apimaker.dev/v1/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
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
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: {
            deep: JSON.stringify([{
                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
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" }
            }
        ]
    }
]);
```

## Get secret key/keys

`g.sys.system.getSecret` calls the [get secret system API](https://docs.apimaker.dev/v1/docs/apis-all/system-apis/system-generated-get-secret-by-name-api.html) from your code, whatever the settings of that API say about HTTP callers.

### Get secret System API

Get secret using global object 'g'.

- Get only one secret key value.

```typescript
await g.sys.system.getSecret("common.secret");
```

- Get multiple secret keys values.

```typescript
await g.sys.system.getSecret(["common.secret","common.secret"]);
```

## Get table metadata

`g.sys.system.getTableMeta` calls the [get table meta system API](https://docs.apimaker.dev/v1/docs/apis-all/system-apis/system-generated-get-table-meta-api.html) from your code, whatever the settings of that API say about HTTP callers.

### Get table metadata System API

Get table metadata using global object 'g'.

```ts
await g.sys.system.getTableMeta({
    instance: 'INSTANCE_NAME',
    database: 'DATABASE_NAME',
    collection: 'COLLECTION_NAME'
});
```

### Multi-tenant
- `instance: "crm::acme"` reads the table in the database of the tenant `acme` of the [multi-tenant](https://docs.apimaker.dev/v1/docs/features/multi-tenant.html) instance `crm`. In a custom API called for a tenant, `instance: "crm"` reads it in the database of that tenant.

```ts
await g.sys.system.getTableMeta({
    instance: 'crm::acme',
    database: 'crm',
    collection: 'customers'
});
```

## Create indexes

`g.sys.system.createIndexes` calls the [create indexes system API](https://docs.apimaker.dev/v1/docs/apis-all/system-apis/system-generated-create-indexes-api.html) from your code, whatever the settings of that API say about HTTP callers.

### Create indexes System API

Create indexes using global object 'g'. The same request works on MongoDB, MySQL, MariaDB, SQL Server, PostgreSQL and Oracle ; an index which exists already is left alone (`EXISTS`), a field the database can not index is `SKIPPED` with the reason, a refusal of the database is `FAILED` with its message.

```ts
const results = await g.sys.system.createIndexes({
    indexes: [
        {
            instance: 'mysql8',
            database: 'inventory',
            table: 'orders',
            fields: [{ name: 'customer_id' }, { name: 'status', order: 'DESC' }],
        },
        {
            instance: 'mongodb',
            database: 'inventory',
            collection: 'products',
            name: 'ux_products_sku',
            unique: true,
            fields: [{ name: 'sku' }],
        },
    ],
    ifNotExists: true,      // default : nothing is created twice
    continueOnError: true,  // default : one refused index does not stop the others
    skipUnindexable: true,  // default : TEXT, json, CLOB... are skipped before the database is asked
});
// results[0] : { status: 'CREATED', name: 'am_ix_orders_customer_id_status_3f9a1c', fields: ['customer_id', 'status'], ... }
// results[1] : { status: 'EXISTS', message: 'The index "ux_products_sku" exists already.', ... }
```

- Without a `name`, the index is called `am_ix_<table>_<fields>_<hash>` (`am_ixu_` when unique), the same in every environment, cut to the limit of the database (30 characters on Oracle).
- `order` : `ASC`, `DESC`, `HASHED` and `TEXT` (MongoDB) ; `nullsFirst: true` on PostgreSQL. `type` : `FULLTEXT` or `SPATIAL` (MySQL), `CLUSTERED`, `XML`, `SPATIAL` (SQL Server), `hash`, `gin`, `gist`, `spgist`, `brin` (PostgreSQL). `method` : `BTREE`, `HASH`, `RTREE` (MySQL).
- This is the call the migration script `am_index_maker` of [Index Maker](https://docs.apimaker.dev/v1/extensions/index_maker/automatic_indexes.html) makes on deploy : a migration script of your own can do the same.

### Multi-tenant
- `instance: "crm::acme"` creates the index in the database of the tenant `acme` of the [multi-tenant](https://docs.apimaker.dev/v1/docs/features/multi-tenant.html) instance `crm`. In a custom API called for a tenant, `instance: "crm"` creates it in the database of that tenant.

```ts
await g.sys.system.createIndexes({
    indexes: [{ instance: 'crm::acme', database: 'crm', collection: 'customers', fields: [{ name: 'email' }], unique: true }],
});
```

## Drop indexes

`g.sys.system.dropIndexes` calls the [drop indexes system API](https://docs.apimaker.dev/v1/docs/apis-all/system-apis/system-generated-drop-indexes-api.html) from your code, whatever the settings of that API say about HTTP callers.

### Drop indexes System API

Drop indexes of a table by name using global object 'g'. A name the table does not have is `NOT_FOUND`, not an error, so the call can run again.

```ts
const results = await g.sys.system.dropIndexes({
    instance: 'mysql8',
    database: 'inventory',
    table: 'orders',
    indexes: ['am_ix_orders_customer_id_status_3f9a1c', 'old_idx_status'],
    ifExists: true,         // default : a missing index is NOT_FOUND
    continueOnError: true,  // default : one refused drop does not stop the others
});
// results[0] : { status: 'DROPPED', fields: ['customer_id', 'status'], ... }
// results[1] : { status: 'NOT_FOUND', message: 'The index "old_idx_status" does not exist.', ... }
```

- Several tables at once : give a list of such objects, the results come back in one flat list.
- `instance: "crm::acme"` drops in the database of the tenant `acme` of the multi-tenant instance `crm`.

## Get indexes

`g.sys.system.getIndexes` calls the [get indexes system API](https://docs.apimaker.dev/v1/docs/apis-all/system-apis/system-generated-get-indexes-api.html) from your code, whatever the settings of that API say about HTTP callers.

### Get indexes System API

List the indexes of a table using global object 'g', in the same format for every database.

```ts
const indexes = await g.sys.system.getIndexes({
    instance: 'mysql8',
    database: 'inventory',
    table: 'orders',
});
// [
//     { name: 'PRIMARY', key: { id: 1 }, unique: true },
//     { name: 'am_ix_orders_customer_id_status_3f9a1c', key: { customer_id: 1, status: -1 }, unique: false, method: 'BTREE' },
// ]
```

- `key` holds the fields in order with their direction : `1` ascending, `-1` descending, `hashed` or `text` on MongoDB.
- Several tables at once : give a list of such objects, the answer is a list of lists in the same order.
- `instance: "crm::acme"` reads the table in the database of the tenant `acme` of the multi-tenant instance `crm`.

## Emit event

`g.sys.system.emitEvent` calls the [emit event system API](https://docs.apimaker.dev/v1/docs/apis-all/system-apis/system-generated-emit-event-api.html) from your code, whatever the settings of that API say about HTTP callers.

### Emit event System API

Emit event using global object 'g'.

```ts
await g.sys.system.emitEvent("EVENT_NAME", "EVENT_DATA", ["LISTENERS_NAME"]);
```

## Emit event websocket

`g.sys.system.emitEventWS` calls the [emit WebSocket event system API](https://docs.apimaker.dev/v1/docs/apis-all/system-apis/system-generated-emit-event-ws-api.html) from your code, whatever the settings of that API say about HTTP callers.

### Emit event web-socket System API

Emit event of websocket using global object 'g'.

```ts
await g.sys.system.emitEventWS("EVENT_NAME", "EVENT_DATA");
```

```ts
await g.sys.system.emitEventWS(
    "myEvent", 
    { "name": "Bob" }
);
```

## Is valid data for table/collection

`g.sys.system.isValidDataForTable` calls the [is valid data for table system API](https://docs.apimaker.dev/v1/docs/apis-all/system-apis/system-generated-is-valid-data-for-table-api.html) from your code, whatever the settings of that API say about HTTP callers.

### Validate table data

Test data valid or not using global object 'g'.

```ts
await g.sys.system.isValidDataForTable({
    instance: "INSTANCE_NAME", database: 'DB_NAME', collection: "COLLECTION_NAME",
    data: {
        "field": "fieldValue",
        "field": "fieldValue"
    }
});
```

```ts
await g.sys.system.isValidDataForTable({
    instance: "mongoDB",
    database: "db_inventory",
    collection: "tbl_customers",
    data: {
        "customer_id": 1,
        "first_name": "Bob",
        "last_name": "Lin",
        "last_update": "2006-02-14T23:04:33.000Z",
        "pincode": 382330,
        "isActive": 1
    }
});
```

## Is valid data for custom API

`g.sys.system.isValidDataForCustomAPI` calls the [is valid data for custom API system API](https://docs.apimaker.dev/v1/docs/apis-all/system-apis/system-generated-is-valid-data-for-custom-api.html) from your code, whatever the settings of that API say about HTTP callers.

### Validate custom API body object

Test custom API data valid or not using global object 'g'.

```ts
await g.sys.system.isValidDataForCustomAPI({
    name: "custom_api_name",
    data: {
        "some": "data",
        "some": "data"
    },
    type: "BODY" // BODY | QUERY_PARAMS
});
```

## Is valid data for third party API

`g.sys.system.isValidDataForThirdPartyAPI` calls the [is valid data for third party API system API](https://docs.apimaker.dev/v1/docs/apis-all/system-apis/system-generated-is-valid-data-for-third-party-api.html) from your code, whatever the settings of that API say about HTTP callers.

### Validate third party request body

Test the data is valid for Third party API, using global object 'g'.

```ts
await g.sys.system.isValidDataForThirdPartyAPI({
    apiBundleName: "bundle_name",
    apiVersionName: "api_version",
    name: "api_name",
    type: "BODY", // BODY | QUERY_PARAMS
    data: {
        name: 'hello'
    },
    isArray: false
});
```

## Multi tenant instance updated

`g.sys.system.multiTenantInstanceUpdated` calls the [multi tenant instance updated system API](https://docs.apimaker.dev/v1/docs/apis-all/system-apis/system-generated-multi-tenant-instance-updated-api.html) from your code, whatever the settings of that API say about HTTP callers.

### Multi tenant instance updated System API

After the connection string of a tenant of a [multi-tenant](https://docs.apimaker.dev/v1/docs/features/multi-tenant.html) instance changed in the tenants table, tell API Maker. Every server drops the connection pools of that tenant, and the next request of the tenant connects with the new connection string.

```ts
await g.sys.system.multiTenantInstanceUpdated({ instanceName: 'crm', username: 'acme' });
```

Several instances or tenants at once, each item answered on its own:

```ts
const output = await g.sys.system.multiTenantInstanceUpdated([
    { instanceName: 'crm', username: 'acme' },
    { instanceName: 'billing', username: 'acme' },
]);
// [{ success: true, data: true }, { success: false, data: false, error: { code: 404, message: "..." } }]
```
