diff --git a/.github/workflows/typescript-packages-changesets-npm-release.yml b/.github/workflows/typescript-packages-changesets-npm-release.yml index c20504bba..58680c493 100644 --- a/.github/workflows/typescript-packages-changesets-npm-release.yml +++ b/.github/workflows/typescript-packages-changesets-npm-release.yml @@ -6,6 +6,7 @@ on: - main paths: - "packages/**" + - "!packages/nameguard-python/**" concurrency: ${{ github.workflow }}-${{ github.ref }} diff --git a/.github/workflows/typescript-packages-unit-tests.yml b/.github/workflows/typescript-packages-unit-tests.yml index 8d90af908..a36d6a79a 100644 --- a/.github/workflows/typescript-packages-unit-tests.yml +++ b/.github/workflows/typescript-packages-unit-tests.yml @@ -7,12 +7,14 @@ on: - staging paths: - "packages/**" + - "!packages/nameguard-python/**" pull_request: branches: - main - staging paths: - "packages/**" + - "!packages/nameguard-python/**" env: PROVIDER_URI_MAINNET: ${{ secrets.PROVIDER_URI_MAINNET }} diff --git a/README.md b/README.md index 7f3ac1a57..e9cc58fa5 100644 --- a/README.md +++ b/README.md @@ -320,7 +320,7 @@ The NameKit monorepo contains multiple packages and apps. - nameguard + nameguard Identify and prevent malicious use of ENS names. @@ -382,6 +382,21 @@ The NameKit monorepo contains multiple packages and apps. Preview                  + + + + + AWS Lambda + + + + api.nameguard.io + + AWS Lambda deployment of the NameGuard API + + Preview + + diff --git a/apps/api.nameguard.io/README.md b/apps/api.nameguard.io/README.md index ef97180f1..68ce5460d 100644 --- a/apps/api.nameguard.io/README.md +++ b/apps/api.nameguard.io/README.md @@ -1,88 +1,24 @@ # NameGuard Python -![Tests](https://github.com/namehash/namekit/actions/workflows/ci_api.yml/badge.svg?branch=main) -![Coverage](coverage_badge.svg) +![Deploy](https://github.com/namehash/namekit/actions/workflows/nameguard-api-lambda-deploy.yml/badge.svg?branch=main) -This repository contains the NameGuard AWS Lambda deployment. +## Architecture Summary -## Getting Started +This app provides an AWS Lambda wrapper of the NameGuard Python library that is available on [PyPI](https://pypi.org/project/nameguard/). -### Using the public API +The NameGuard Python library contains an embedded webserver of its own. -NameGuard is hosted at +Please see details of how to configure environment variables, or making example requests in the [NameGuard Python library](/packages/nameguard-python/). -You can make a basic request to the API like this: +## Automated Deployments -```bash -curl https://api.nameguard.io/inspect-name/mainnet/nick.eth -``` - -The API documentation is available at or . - -### Running your own NameGuard instance - -#### Env variables +The following environment variables should be set for the [automated deployment script](/.github/workflows/nameguard-api-lambda-deploy.yml) (in addition to the environment variables required by nameguard-python). ```bash AWS_ROLE - AWS Role used by GitHub actions to create the CloudFormation infrastructure for deploying NameGuard as an AWS Lambda and pushing the latest build image to AWS ECR. SLACK_WEBHOOK_URL - Slack webhook url used by GitHub actions to send notifications of deployment success or failure to the dev team's slack channel. ``` -#### Installing the library - -NameGuard is available as a Python library on [PyPI](https://pypi.org/project/nameguard/). You can install it with `pip`: - -```bash -pip install nameguard -``` - -#### Setting Provider URIs - -NameGuard uses the specified Provider endpoint (e.g. Alchemy, Infura, your own Ethereum node, etc...) for `secure-primary-name/`. Provider endpoints have to be set by environment variables, e.g.: - -```bash -export PROVIDER_URI_MAINNET=https://eth-mainnet.g.alchemy.com/v2/[YOUR_ALCHEMY_API_KEY] -export PROVIDER_URI_SEPOLIA=https://eth-sepolia.g.alchemy.com/v2/[YOUR_ALCHEMY_API_KEY] -export ALCHEMY_URI_MAINNET=https://eth-mainnet.g.alchemy.com/v2/[YOUR_ALCHEMY_API_KEY] -export ALCHEMY_URI_SEPOLIA=https://eth-sepolia.g.alchemy.com/v2/[YOUR_ALCHEMY_API_KEY] -export ENS_SUBGRAPH_URL_MAINNET="https://gateway-arbitrum.network.thegraph.com/api/[YOUR_SUBGRAPH_API_KEY]/subgraphs/id/5XqPmWe6gjyrJtFn9cLy237i4cWw2j9HcUJEXsP5qGtH" -export ENS_SUBGRAPH_URL_SEPOLIA="https://gateway-arbitrum.network.thegraph.com/api/[YOUR_SUBGRAPH_API_KEY]/subgraphs/id/DmMXLtMZnGbQXASJ7p1jfzLUbBYnYUD9zNBTxpkjHYXV" -``` - -#### Starting the web server - -A FastAPI application is included in the `nameguard.web_api` module. The default installation from PyPI does not include an ASGI server, so you will need to install one separately. For example, to install [uvicorn](https://www.uvicorn.org): - -```bash -pip install 'uvicorn[standard]' -``` - -You can start the web server with: - -```bash -uvicorn nameguard.web_api:app -``` - -Make an example request: - -```bash -curl -d '{"name":"nick.eth", "network_name": "mainnet"}' -H "Content-Type: application/json" -X POST http://localhost:8000/inspect-name -# { -# "rating": "pass", -# "risk_count": 0, -# "highest_risk": null, -# "name": "nick.eth", -# "namehash": "0x05a67c0ee82964c4f7394cdd47fee7f4d9503a23c09c38341779ea012afe6e00", -# "normalization": "normalized", -# "checks": [...], -# "labels": [...], -# "canonical_name": "nick.eth", -# "title": "Looks Good", -# "subtitle": "All security checks passed!", -# "beautiful_name": "nick.eth" -# } -``` - ## License Licensed under the MIT License, Copyright © 2023-present [NameHash Labs](https://namehashlabs.org). diff --git a/apps/api.nameguard.io/package.json b/apps/api.nameguard.io/package.json index efb3937fe..f8342b94c 100644 --- a/apps/api.nameguard.io/package.json +++ b/apps/api.nameguard.io/package.json @@ -7,9 +7,9 @@ "repository": { "type": "git", "url": "git+https://github.com/namehash/namekit.git", - "directory": "api" + "directory": "apps/api.nameguard.io" }, - "homepage": "https://github.com/namehash/namekit/tree/main/api", + "homepage": "https://github.com/namehash/namekit/tree/main/apps/api.nameguard.io", "keywords": [ "ENS", "NameKit", diff --git a/apps/docs.nameguard.io/self-hosting.mdx b/apps/docs.nameguard.io/self-hosting.mdx index ec3866d34..6e7cbd473 100644 --- a/apps/docs.nameguard.io/self-hosting.mdx +++ b/apps/docs.nameguard.io/self-hosting.mdx @@ -58,12 +58,12 @@ git clone https://github.com/namehash/namekit Then install the dependencies using `poetry`: ```bash -cd nameguard +cd packages/nameguard-python poetry install ``` You can now run the tests for all checks outlined in the [specification](/specification). From the root of the project, run the following command: ```bash -pytest ./api/tests/ +pytest ./packages/nameguard-python/tests/ ``` diff --git a/apps/nameguard.io/src/components/organisms/DevelopersSection.tsx b/apps/nameguard.io/src/components/organisms/DevelopersSection.tsx index 6761ff942..76be7148e 100644 --- a/apps/nameguard.io/src/components/organisms/DevelopersSection.tsx +++ b/apps/nameguard.io/src/components/organisms/DevelopersSection.tsx @@ -54,7 +54,7 @@ const devElements: ListSectionElement[] = [ ), - link: "https://github.com/namehash/namekit/tree/main/api", + link: "https://github.com/namehash/namekit/tree/main/packages/nameguard-python", }, { header: ( @@ -206,7 +206,7 @@ const devElements: ListSectionElement[] = [ ), - link: "https://github.com/namehash/namekit/blob/main/api/serverless.yml", + link: "https://github.com/namehash/namekit/blob/main/apps/api.nameguard.io", }, { header: ( diff --git a/apps/nameguard.io/src/components/organisms/RoadMap.tsx b/apps/nameguard.io/src/components/organisms/RoadMap.tsx index ba1405f29..29412f71e 100644 --- a/apps/nameguard.io/src/components/organisms/RoadMap.tsx +++ b/apps/nameguard.io/src/components/organisms/RoadMap.tsx @@ -104,7 +104,7 @@ export function RoadMap() { Build{" "} @@ -141,7 +141,7 @@ export function RoadMap() { Made it easy for anyone to{" "} diff --git a/nameguard.md b/nameguard.md deleted file mode 100644 index 7f1fee790..000000000 --- a/nameguard.md +++ /dev/null @@ -1,109 +0,0 @@ -# NameHash NameGuard - -The NameHash team is proud to present NameGuard, a tool for identifying and preventing malicious use of ENS names. - -- Offers multiple levels of protection - - Impersonated name detection - - Confusable grapheme detection - - International accessibility checks - - Rendering checks for different fonts - - ENSIP-15 verification with detailed explanations and auto-suggestions (provided by [ens-normalize-python](https://github.com/namehash/ens-normalize-python)) - - Punycode and DNS hostname compatibility checks - - and more! -- Provides a unified rating system for entire names, as well as detailed explanations for each check - - :green_circle: Pass: no issues found - - :yellow_circle: Warn: potential issues found - - :red_circle: Fail: serious issues found -- Supports many use cases - - Standalone Python library ([PyPI](https://pypi.org/project/nameguard/)) - - ASGI web server - - [Amazon AWS Lambda](https://aws.amazon.com/lambda/) handler - -⚠️ **This SDK is BETA. Things will change based on the community feedback.** - -## Getting Started - -### [Try the official web app](https://nameguard.io) - -### Using the public API - -NameGuard is hosted at - -You can make a basic request to the API like this: - -```bash -curl https://api.nameguard.io/inspect-name/mainnet/nick.eth -``` - -The API documentation is available at or . - -### Using the SDK - -Quickstart: - -```bash -npm install @namehash/nameguard -``` - -```ts -import { nameguard } from "@namehash/nameguard"; -await nameguard.inspectName("nick.eth"); -``` - -See the [SDK README](./packages/sdk/README.md) for more details. - -### Using the Python library - -Quickstart: - -```bash -pip install nameguard -``` - -```python -from nameguard import NameGuard -ng = NameGuard() -await ng.inspect_name(network_name='mainnet', name='nick.eth') -``` - -See the [NameGuard Python README](./api/README.md) for more details. - -### Running your own NameGuard instance - -See the [NameGuard Python README](./api/README.md) for more details. - -## NameGuard Specification - -### Checks - -1. **Impersonation**: Detects names that could be trying to impersonate a different name by using similar characters. Example: [`vitalìk.eth`](https://nameguard.io/inspect/vitalìk.eth) - -2. **Confusables**: Detects characters that can be confused with other characters. Example: [`vitalìk.eth`](https://nameguard.io/inspect/vitalìk.eth) - -3. **Font Support**: Checks if the characters in the name are supported by commonly used fonts. Example: [`🛈.eth`](https://nameguard.io/inspect/🛈.eth) - -4. **Invisibles**: Detects invisible characters. Example: [`888‍‍.eth`](https://nameguard.io/inspect/888‍‍.eth) - -5. **Typing Difficulty**: Detects names that are difficult to type on some keyboards. Example: [`żółć.eth`](https://nameguard.io/inspect/żółć.eth) - -6. **Mixed Scripts**: Detects names that contain characters from multiple scripts or alphabets. Example: [`あア.eth`](https://www.nameguard.io/inspect/あア.eth) - -7. **Name Wrapper**: Checks if the name is supported by the new ENS Name Wrapper. Example: [`abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd.eth`](https://nameguard.io/inspect/abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd.eth) - -8. **ENSIP-15**: Checks if the name is normalized according to ENSIP-15. Example: [`bitсoin.eth`](https://nameguard.io/inspect/bitсoin.eth) - -9. **Punycode**: Checks if the name is compatible with Punycode encoding. Example: [`ab--abc.eth`](https://www.nameguard.io/inspect/ab--abc.eth) - -10. **Unknown Labels**: Checks if the name contains unknown labels. Example: [`[5bc926fc40cc7c49e0df6dddf26e4dc7b9d6d32f4a55d4f0670320dbf414afd2].byongdok.eth`](https://nameguard.io/inspect/[5bc926fc40cc7c49e0df6dddf26e4dc7b9d6d32f4a55d4f0670320dbf414afd2].byongdok.eth) - -11. **Decentralized Name**: Checks if the name is decentralized (unruggable). Example: [`example.com`](https://www.nameguard.io/inspect/example.com) - -12. **NameWrapper fuses**: Checks that the NameWrapper configuration of a name is safe. - -13. **Uninspected Name**: Checks if the name is exceptionally long and would not be inspected by NameGuard for performance reasons. - -## License - -Licensed under the MIT License, Copyright © 2023-present [NameHash Labs](https://namehashlabs.org). - -See [LICENSE](./LICENSE) for more information. \ No newline at end of file diff --git a/packages/nameguard-python/README.md b/packages/nameguard-python/README.md index f6f027cef..6710a97ac 100644 --- a/packages/nameguard-python/README.md +++ b/packages/nameguard-python/README.md @@ -3,10 +3,33 @@ ![Tests](https://github.com/namehash/namekit/actions/workflows/nameguard-api-unit-tests.yml/badge.svg?branch=main) ![Coverage](https://github.com/namehash/namekit/raw/packages/nameguard-python/coverage_badge.svg) -This repository contains the core logic for NameGuard, a python library and web API server. +The NameHash team is proud to present NameGuard, a tool for identifying and preventing malicious use of ENS names. + +- Offers multiple levels of protection + - Impersonated name detection + - Confusable grapheme detection + - International accessibility checks + - Rendering checks for different fonts + - ENSIP-15 verification with detailed explanations and auto-suggestions (provided by [ens-normalize-python](https://github.com/namehash/ens-normalize-python)) + - Punycode and DNS hostname compatibility checks + - and more! +- Provides a unified rating system for entire names, as well as detailed explanations for each check + - :green_circle: Pass: no issues found + - :yellow_circle: Warn: potential issues found + - :red_circle: Fail: serious issues found +- Supports many use cases + - Standalone Python library ([PyPI](https://pypi.org/project/nameguard/)) + - ASGI web server + - [Amazon AWS Lambda](https://aws.amazon.com/lambda/) handler + +⚠️ **This package and API is BETA. Things will change based on community feedback.** ## Getting Started +This package contains the core logic for NameGuard, a python library and web API server. + +### [Try the official web app](https://nameguard.io) + ### Using the public API NameGuard is hosted at @@ -19,16 +42,22 @@ curl https://api.nameguard.io/inspect-name/mainnet/nick.eth The API documentation is available at or . -### Running your own NameGuard instance +### Using the TypeScript SDK -#### Env variables +Quickstart: ```bash -AWS_ROLE - AWS Role used by GitHub actions to create the CloudFormation infrastructure for deploying NameGuard as an AWS Lambda and pushing the latest build image to AWS ECR. -SLACK_WEBHOOK_URL - Slack webhook url used by GitHub actions to send notifications of deployment success or failure to the dev team's slack channel. +npm install @namehash/nameguard +``` + +```ts +import { nameguard } from "@namehash/nameguard"; +await nameguard.inspectName("nick.eth"); ``` -#### Installing the library +See the [SDK README](./packages/nameguard-sdk/README.md) for more details. + +### Using the Python library NameGuard is available as a Python library on [PyPI](https://pypi.org/project/nameguard/). You can install it with `pip`: @@ -36,9 +65,17 @@ NameGuard is available as a Python library on [PyPI](https://pypi.org/project/na pip install nameguard ``` -#### Setting Provider URIs +```python +from nameguard import NameGuard +ng = NameGuard() +await ng.inspect_name(network_name='mainnet', name='nick.eth') +``` + +See the [NameGuard Python README](./apps/api.nameguard.io/README.md) for more details. + +### Environment Variables -NameGuard uses the specified Provider endpoint (e.g. Alchemy, Infura, your own Ethereum node, etc...) for `secure-primary-name/`. Provider endpoints have to be set by environment variables, e.g.: +NameGuard uses the specified Provider endpoints (e.g. Alchemy, Infura, your own Ethereum node, etc...) for `secure-primary-name/`. Provider endpoints have to be set by environment variables, e.g.: ```bash export PROVIDER_URI_MAINNET=https://eth-mainnet.g.alchemy.com/v2/[YOUR_ALCHEMY_API_KEY] @@ -49,7 +86,7 @@ export ENS_SUBGRAPH_URL_MAINNET="https://gateway-arbitrum.network.thegraph.com/a export ENS_SUBGRAPH_URL_SEPOLIA="https://gateway-arbitrum.network.thegraph.com/api/[YOUR_SUBGRAPH_API_KEY]/subgraphs/id/DmMXLtMZnGbQXASJ7p1jfzLUbBYnYUD9zNBTxpkjHYXV" ``` -#### Starting the web server +### Starting the webserver A FastAPI application is included in the `nameguard.web_api` module. The default installation from PyPI does not include an ASGI server, so you will need to install one separately. For example, to install [uvicorn](https://www.uvicorn.org): @@ -98,10 +135,10 @@ poetry install To run nameguard tests locally, just run pytest from the root directory: ```bash -pytest ./api/tests/ +pytest ./packages/nameguard-python/tests/ ``` -NameGuard also provides an option to run API tests (`api/tests/test_api.py`) +NameGuard also provides an option to run API tests (`packages/nameguard-python/tests/test_api.py`) against a remote host (e.g. Lambda) where a NameGuard instance is running. To enable this, you will need to set an environment variable `LAMBDA_ROOT_URL` to specify the remote host URL. @@ -109,7 +146,7 @@ To enable this, you will need to set an environment variable This can be done like this: ```bash -LAMBDA_ROOT_URL=https://api.nameguard.io poetry run pytest api/tests/test_api.py +LAMBDA_ROOT_URL=https://api.nameguard.io poetry run pytest packages/nameguard-python/tests/test_api.py ``` ### Using the AWS Lambda handler @@ -118,6 +155,8 @@ NameGuard includes a handler for [Amazon AWS Lambda](https://aws.amazon.com/lamb Check out the included [Dockerfile](./Dockerfile) for an example of how to build a Lambda container image. +See the [AWS Lambda deployment scripts](./apps/api.nameguard.io/) for more details. + ### Disable monkeypatch tests By default, the tests are using mock responses from external APIs. If you want to run tests using real requests to external APIs then set `MONKEYPATCH=0`. @@ -126,6 +165,36 @@ By default, the tests are using mock responses from external APIs. If you want t MONKEYPATCH=0 poetry run pytest ``` +## NameGuard Specification + +### Checks + +1. **Impersonation**: Detects names that could be trying to impersonate a different name by using similar characters. Example: [`vitalìk.eth`](https://nameguard.io/inspect/vitalìk.eth) + +2. **Confusables**: Detects characters that can be confused with other characters. Example: [`vitalìk.eth`](https://nameguard.io/inspect/vitalìk.eth) + +3. **Font Support**: Checks if the characters in the name are supported by commonly used fonts. Example: [`🛈.eth`](https://nameguard.io/inspect/🛈.eth) + +4. **Invisibles**: Detects invisible characters. Example: [`888‍‍.eth`](https://nameguard.io/inspect/888‍‍.eth) + +5. **Typing Difficulty**: Detects names that are difficult to type on some keyboards. Example: [`żółć.eth`](https://nameguard.io/inspect/żółć.eth) + +6. **Mixed Scripts**: Detects names that contain characters from multiple scripts or alphabets. Example: [`あア.eth`](https://www.nameguard.io/inspect/あア.eth) + +7. **Name Wrapper**: Checks if the name is supported by the new ENS Name Wrapper. Example: [`abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd.eth`](https://nameguard.io/inspect/abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd.eth) + +8. **ENSIP-15**: Checks if the name is normalized according to ENSIP-15. Example: [`bitсoin.eth`](https://nameguard.io/inspect/bitсoin.eth) + +9. **Punycode**: Checks if the name is compatible with Punycode encoding. Example: [`ab--abc.eth`](https://www.nameguard.io/inspect/ab--abc.eth) + +10. **Unknown Labels**: Checks if the name contains unknown labels. Example: [`[5bc926fc40cc7c49e0df6dddf26e4dc7b9d6d32f4a55d4f0670320dbf414afd2].byongdok.eth`](https://nameguard.io/inspect/[5bc926fc40cc7c49e0df6dddf26e4dc7b9d6d32f4a55d4f0670320dbf414afd2].byongdok.eth) + +11. **Decentralized Name**: Checks if the name is decentralized (unruggable). Example: [`example.com`](https://www.nameguard.io/inspect/example.com) + +12. **NameWrapper fuses**: Checks that the NameWrapper configuration of a name is safe. + +13. **Uninspected Name**: Checks if the name is exceptionally long and would not be inspected by NameGuard for performance reasons. + ## License Licensed under the MIT License, Copyright © 2023-present [NameHash Labs](https://namehashlabs.org). diff --git a/packages/nameguard-sdk/README.md b/packages/nameguard-sdk/README.md index 295ffd61c..a11700c25 100644 --- a/packages/nameguard-sdk/README.md +++ b/packages/nameguard-sdk/README.md @@ -1,5 +1,6 @@ # NameGuard SDK +![Tests](https://github.com/namehash/namekit/actions/workflows/nameguard-end-to-end-tests.yml/badge.svg?branch=main) ![NPM Version](https://img.shields.io/npm/v/@namehash/nameguard) [NameGuard](https://nameguard.io) is designed to inspect and prevent malicious use of Ethereum Name Service (ENS) names. It provides a comprehensive set of functionalities to check the normalization status of names, labels, and graphemes, conduct various safety checks on ENS names, and verify the authenticity of ".eth" names in NFTs. diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ceed92365..5768129eb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -465,16 +465,6 @@ importers: specifier: 2.1.2 version: 2.1.2(@types/node@22.7.4) - packages/nameguard-python: - dependencies: - serverless: - specifier: 3.39.0 - version: 3.39.0 - devDependencies: - serverless-prune-plugin: - specifier: 2.0.2 - version: 2.0.2(serverless@3.39.0) - packages/nameguard-react: dependencies: '@headlessui-float/react': diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index ab4cfd6b2..e933055a6 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,5 +1,5 @@ packages: - "apps/**" - "packages/**" + - "!packages/nameguard-python/**" - "internal/**" - - "api"