> ## Documentation Index
> Fetch the complete documentation index at: https://docs.natural.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Manage customer access

> Manage agents across your connected customers

See which customers your agents act for, inspect what each one granted, and revoke an agent or a pending invitation whenever you need to.

<Snippet file="shared/prerequisites.mdx" />

## See who your agents act for

Your customers list holds every customer who has connected an agent to you. Each entry's `id` is the party ID you pass as `customerPartyId` when you act for them, and each entry shows the agents acting for that customer, with the permissions and `perTransaction` limit in force. Read it with [`GET /customers`](/api-reference/customers/list-customers).

<CodeGroup>
  ```python Python theme={null}
  from naturalpay import Natural

  client = Natural()
  customers = client.customers.list()

  for customer in customers.data:
      print(customer.id, customer.attributes.name)
  ```

  ```typescript TypeScript theme={null}
  import Natural from "@naturalpay/sdk";

  const client = new Natural();
  const customers = await client.customers.list();

  for (const customer of customers.data) {
    console.log(customer.id, customer.attributes.name);
  }
  ```

  ```bash CLI theme={null}
  natural customers list
  ```

  ```text MCP theme={null}
  List my active customers and the agents acting for them.
  ```

  ```bash cURL theme={null}
  curl https://api.natural.com/customers \
    -H "Authorization: Bearer $NATURAL_API_KEY"
  ```
</CodeGroup>

Filter by status: `active` for accepted access, `pending` for unaccepted invitations, or `all` for both. A pending invitation stays on your invitations list until the customer accepts.

## Inspect one customer

Read a single customer with [`GET /customers/{customerId}`](/api-reference/customers/get-customer) to see exactly which agents, permissions, and limits are in force before you change anything. The `customerId` is that customer's party ID.

<CodeGroup>
  ```python Python theme={null}
  customer = client.customers.get("pty_019cd1798d617f65a79cb965dda9eac3")

  print(customer.data.id, customer.data.attributes.agents)
  ```

  ```typescript TypeScript theme={null}
  const customer = await client.customers.get({
    customerId: "pty_019cd1798d617f65a79cb965dda9eac3",
  });

  console.log(customer.data.id, customer.data.attributes.agents);
  ```

  ```bash CLI theme={null}
  natural customers get --customer-id pty_019cd1798d617f65a79cb965dda9eac3
  ```

  ```text MCP theme={null}
  Show me customer pty_019cd1798d617f65a79cb965dda9eac3 and what my agents can do for them.
  ```

  ```bash cURL theme={null}
  curl https://api.natural.com/customers/pty_019cd1798d617f65a79cb965dda9eac3 \
    -H "Authorization: Bearer $NATURAL_API_KEY"
  ```
</CodeGroup>

## See pending invitations

Invitations you have sent but nobody has accepted yet live on a separate list. Read it with [`GET /customers/invitations`](/api-reference/customers/list-customer-invitations) to confirm what is still open before you revoke.

<CodeGroup>
  ```python Python theme={null}
  pending = client.customers.list_invitations()

  for invitation in pending.data:
      print(invitation.attributes.email, invitation.attributes.status)
  ```

  ```typescript TypeScript theme={null}
  const pending = await client.customers.listInvitations();

  for (const invitation of pending.data) {
    console.log(invitation.attributes.email, invitation.attributes.status);
  }
  ```

  ```bash CLI theme={null}
  natural customers listInvitations
  ```

  ```text MCP theme={null}
  Show my pending customer invitations.
  ```

  ```bash cURL theme={null}
  curl https://api.natural.com/customers/invitations \
    -H "Authorization: Bearer $NATURAL_API_KEY"
  ```
</CodeGroup>

Each recipient groups its `agentInvitations`, one `adi_*` per agent you invited them to. You revoke by that `invitationId`.

## Revoke a pending invitation

Cancel an invitation the recipient has not accepted with [`DELETE /customers/invitations/{invitationId}`](/api-reference/customers/revoke-customer-invitation), and they can no longer accept it.

<CodeGroup>
  ```python Python theme={null}
  client.customers.revoke_invitation("adi_550e8400e29b41d4a716446655440000")
  ```

  ```typescript TypeScript theme={null}
  await client.customers.revokeInvitation({
    invitationId: "adi_550e8400e29b41d4a716446655440000",
  });
  ```

  ```bash CLI theme={null}
  natural customers revokeInvitation --invitation-id adi_550e8400e29b41d4a716446655440000
  ```

  ```bash cURL theme={null}
  curl -X DELETE https://api.natural.com/customers/invitations/adi_550e8400e29b41d4a716446655440000 \
    -H "Authorization: Bearer $NATURAL_API_KEY"
  ```
</CodeGroup>

The invitation's `status` becomes `CANCELED` with a `cancelReason` of `DEVELOPER_REVOKED`. Revoking an already-canceled or already-accepted invitation is a no-op, so retries are safe.

## Revoke an agent's access

Once a customer has accepted, you revoke per agent. [`DELETE /customers/{customerId}/agents/{agentId}`](/api-reference/customers/revoke-agent-access) strips one agent's authority over that customer immediately. `customerId` is the customer's party ID, and `agentId` is the agent you are pulling.

<CodeGroup>
  ```python Python theme={null}
  client.customers.revoke_agent(
      "pty_019cd1798d617f65a79cb965dda9eac3",
      "agt_019cd1798d637a4da75dce386343931d",
  )
  ```

  ```typescript TypeScript theme={null}
  await client.customers.revokeAgent({
    customerId: "pty_019cd1798d617f65a79cb965dda9eac3",
    agentId: "agt_019cd1798d637a4da75dce386343931d",
  });
  ```

  ```bash CLI theme={null}
  natural customers revokeAgent \
    --customer-id pty_019cd1798d617f65a79cb965dda9eac3 \
    --agent-id agt_019cd1798d637a4da75dce386343931d
  ```

  ```bash cURL theme={null}
  curl -X DELETE https://api.natural.com/customers/pty_019cd1798d617f65a79cb965dda9eac3/agents/agt_019cd1798d637a4da75dce386343931d \
    -H "Authorization: Bearer $NATURAL_API_KEY"
  ```
</CodeGroup>

If the agent you remove is the last one acting for that customer, the whole customer resource comes back with `meta.deleted: true`, and the relationship is over. Revocation is idempotent: pulling an agent that is already gone changes nothing, so it is safe to retry.

<Snippet file="shared/webhook-connect-access.mdx" />
