Using the Indent API
Indent provides an API for adding approvals to your applications, internal tools, and AI agents.
This API provides a general-purpose interface for requesting human review, allowing developers to secure any workflow with simple approvals:
- Dangerous or sensitive actions like deleting a project
- AI agents that need human review for edge cases
- Low-code internal tools (Retool, Zapier, etc) that need human review
- JavaScript
- Python
- LangChain (Python)
import { approval } from '@indent/approvals'
try {
const petition = await approval({
reason,
resources: [{ kind: 'password_reset', id: 'user_123' }]
})
console.log('Petition was approved, resetting password', petition)
} catch (err) {
console.error('Petition was not approved, alerting admin', err)
}
from approvals import approval, Resource
await approval({
reason="unable to login",
resources=[Resource(kind="password_reset", id="user_123")]
})
from approvals.using.langchain import HumanApprovalCallbackHandler
from langchain.tools import ShellTool
tool = ShellTool(callbacks=[HumanApprovalCallbackHandler()])
print(tool.run("ls /usr"))
Try the quickstart for:
Indent Approval Kit
To install the official Python bindings, run the following command:
pip install approvals
To install the official Node.js library, run the following command in your Node.js project directory:
npm install @indent/approvals
The Indent Approval Kit is a higher-level abstraction that makes it easier to create and manage approvals. Both of these modules export an interface for creating and managing approvals.
Adding await approval
Wherever you want to add an approval, you can add await approval
to your code. This will block execution until the approval is granted.
from approvals import approval, Resource
async def delete_project(user, project):
await approval({
petitioners=[Resource(kind="user", id=user.id)],
reason="to delete project",
"resources": [Resource(kind="delete_project", id=project.id)]
})
Now, when a user requests to delete a project, their request will automatically route to the #on-call
Slack channel for an engineer to review. Here's that flow in action:
How await approval
works
Instead of handling requests to the Indent API directly, you can use await approval
in JavaScript or Python as a control valve that blocks code execution temporarily until there's an approval.
Here's pseudo-code that describes what the function is doing under the hood:
async def approval(req, opts):
# 0. check if there is an existing petition
petition = await indent.petition.list(
# hash(requesterEmail, resourceKind, resourceId)
unique_key(request)
)
# 1. create a petition
if petition is None:
petition = await indent.petition.create(req)
# 2. wait for the petition to be approved
#
# - some petitions are approved immediately, like if on-call
# - others require human review
retries = opts.retries or 5
while petition.state.status.phase == 'open':
petition = await indent.petition.get(petition.id)
await sleep(2)
# 3. return the petition if granted or raise error if closed
if petition.state.status.phase == 'granted':
return petition
else:
raise Exception('Petition was not approved')
Making requests
With Indent, your account is called a Space since it holds all your data and configuration. Each Space has a unique identifier that we'll refer to as INDENT_SPACE
that you'll use to make requests.
You can paste the command below into your terminal to make your first API request. Make sure to replace $INDENT_SPACE
and $INDENT_API_TOKEN
with your API key.
curl https://platform.indentapis.com/v1/spaces/$INDENT_SPACE/resources \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $INDENT_API_TOKEN"
Indent API libraries
To make it easier to interact with the Indent API, we provide official libraries for Python and Node.js.
To install the official Python bindings, run the following command:
pip install indentapi
To install the official Node.js library, run the following command in your Node.js project directory:
npm install @indent/api
Here's an example of how to use the Node.js bindings to create a petition:
import { IndentAPI } from '@indent/api'
// using INDENT_SPACE and INDENT_API_TOKEN from env vars
const indent = new IndentAPI({
spaceName: 'acmecorp', // defaults to process.env["INDENT_SPACE"]
apiToken: '*****' // defaults to process.env["INDENT_API_TOKEN"]
})
await indent.petition.create({
reason: 'to complete task',
resources: [{ kind: 'action', id: 'approval+123' }]
})
Authentication
The Indent API uses API keys for authentication. Visit your API key page to retrieve the API key you'll use in your requests.
Remember that your API key is a secret! Do not share it with others or expose it in any client-side code (browsers, native apps). Production requests must be routed through your own backend server where your API key can be securely loaded from an environment variable or key management service.
All API requests should include your API token in an Authorization HTTP header as follows:
Authorization: Bearer INDENT_API_TOKEN
There are two kinds of Indent API tokens:
User-based
As short-lived secrets (under 24 hours), user access tokens are used to make requests on behalf of a human user. They are formatted as JSON Web Token (JWT) identifying a specific user and can be used to take actions on their behalf like create, update, and delete petitions.
Why are they short-lived?
Since these tokens identify users and can be used to take action their behalf, they carry security risk that needs to be mitigated. Indent uses two-factor authentication, identity provider verification, and other controls to ensure security for users.
For long-lived API tokens, use service accounts.
Service account-based
Service account tokens are long-lived secrets used to retrieve access tokens for the service account. Once the client exchanges the refresh token for an access token, it can be used as
INDENT_API_TOKEN
to authorize requests. The official libraries handle this exchange for you.
curl https://platform.indentapis.com/v1/auth/token \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $REFRESH_TOKEN"
# { "access_token": "*****", ... }
curl https://platform.indentapis.com/v1/spaces/$INDENT_SPACE/petitions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{
"petition": {
"reason": "to complete task",
"resources": [{ "kind": "action", "id": "approval+123" }],
}
}'