Skip to main content

Least privilege customer access with Indent

Learn how to submit your first approval request using Next.js and Indent Approval Kit.


1. Install

Install the Indent JavaScript SDK and Approval Kit:

npm install --save @indent/api @indent/approvals

2. Get your API key

First, you'll need an Indent space and API token which you can find here:

Current User
Sign in to get API key
  • Can take actions on your behalf
  • Appears in audit log as you
Indent Space
Access Token
Note: this token is short lived and will expire soon

The INDENT_SPACE is the Indent account you want to use for requests and an INDENT_API_TOKEN which is used for authentication. There are two kinds of API tokens: short-lived user access tokens and long-lived service account tokens. Read more about API authentication.

3. Upload customers to Indent

Before we can request access to customers, we'll need to load them into Indent. We'll first list the customers from our database (abstracted as ./db) and use the Indent JavaScript SDK to upload after transforming into the Indent Resource Format:

import { IndentAPI } from '@indent/api'
import db from './db'

const client = new IndentAPI()

async function upload() {
const customers = await db.customers.list()

await client.resource.bulkUpdate({
resources: => ({
kind: 'customer',
labels: { plan: c.plan }


Either on a recurring schedule or when customers are created or updated, we'll want to upload them to Indent. In this case, we'll just run this script:

node upload.js

4. Add await approval

Now that we have customers in Indent, we can request access to them:

import { approval, getErrorKind } from '@indent/approvals'
import { getCurrentUser } from './auth'

async function requestCustomerAccess(ctx, customerId) {
try {
const user = await getCurrentUser(ctx)

await approval({
petitioners: [{ kind: 'user', id:, email: }],
resources: [{ kind: 'customer', id: customerId }]

return { ok: true }
} catch (err) {
switch (getErrorKind(err)) {
case 'waiting':
// Once granted, it will auto-approve next time
return { ok: false, status: 'waiting' }
case 'denied':
// Denied by reviewer or policy
return { ok: false, status: 'denied' }
return { ok: false, status: 'unknown' }

Now, when a member of staff clicks "Request Access" in the admin portal, the API will request access on their behalf and wait for approval.