> **Can't find what you're looking for?** Use `search_docs` on the docs MCP server at `https://docs.prividium.com/api/mcp` to find what you need.
>
> **Have feedback?** Use `submit_feedback` on the same MCP server.

M2M applications represent machine principals that authenticate programmatically against Prividium. Unlike OAuth
applications, they do not handle end-user login flows. Unlike tenants, they do not manage users. Instead, they use a set
of assigned roles to access RPC methods and event data.

Prividium is moving machine-to-machine integrations toward M2M applications over time. Use M2M applications as the
forward-looking model for new machine principals.

## Overview

* **Roles**: Assigned roles are used for RPC authorization and event visibility checks.
* **Credentials**: The admin UI manages API keys for programmatic authentication.
* **Network Restrictions**: API-key authentication is allowed only from whitelisted IP addresses.
* **Organizations**: M2M applications can be linked to one or more organizations to act on behalf of their users.

## Manage M2M Applications

Admins manage M2M applications directly through the dashboard.

### 1. Open the M2M Applications page

1. Go to the **Admin Dashboard**.
2. Select **M2M Apps** from the sidebar.
3. Review the list of M2M applications with their names, assigned roles, and descriptions.

### 2. Create an M2M application

1. Click **New M2M app**.
2. Fill in the application details:
   * **M2M App Name** (required): A descriptive name for the machine principal.
   * **Description**: Optional summary of the application or workload.
3. Assign one or more **Roles**.
4. Click **Create M2M App**.

### 3. Edit an M2M application

1. Click the application row in the list.
2. Click **Edit M2M App**.
3. Update the name, description, or assigned roles.
4. Click **Save Changes**.

The detail view also displays read-only metadata:

* **M2M App ID**
* **Created At**
* **Updated At**

### 4. Delete an M2M application

1. Open the application by clicking its row.
2. Click **Delete M2M App**.
3. Confirm the deletion.

:::info[IMPORTANT]
Deleting an M2M application removes its principal identity and revokes future access through that record. This action
cannot be undone.
:::

## Authentication Model

The admin UI manages API-key access for M2M applications. It does not expose a public key, wallet address, or other
signing identity field for M2M apps.

### API Key Authentication

API keys provide an alternative server-to-server authentication method when interactive wallet signing is not practical.
Admins create and revoke these credentials from the M2M application detail page.

## API Keys

An API key is `priv_sk_` followed by 64 letters or digits, 72 characters in total. Clients send it in the `X-API-Key`
header. The first 12 characters form the key prefix that the admin panel shows to identify the key.

### Create an API Key

1. Open an M2M application.
2. Go to the **API Keys** tab.
3. Click **Add API Key**.
4. Enter a **Name** for the key.
5. Select an **Expiration Date**.
6. Click **Create**.

:::info[IMPORTANT]
The full API key is displayed only once when it is created. Copy it immediately and store it securely.
:::

### Manage API Keys

The API Keys tab displays:

| Column     | Description                                                 |
| ---------- | ----------------------------------------------------------- |
| Name       | Descriptive name for the key                                |
| Key Prefix | First characters of the key for identification              |
| Status     | Active, Expired, or Revoked                                 |
| Expires    | Expiration date                                             |
| Last Used  | Timestamp of the most recent successful API-key use         |
| Last IP    | Source IP address of the most recent successful API-key use |

To revoke a key:

1. Find the key in the list.
2. Click **Revoke**.
3. Confirm the action.

Revoked keys are invalid immediately and cannot be restored.

## IP Whitelisting

IP whitelisting restricts which source IP addresses can authenticate with API keys for an M2M application. Entries can
be individual IP addresses or CIDR ranges (e.g., `10.42.0.0/16`).

:::info[IMPORTANT]
When the IP whitelist is empty, API-key authentication is rejected from all IP addresses. Add at least one entry
before relying on API keys.
:::

### Add an IP Address

1. Open an M2M application.
2. Go to the **IP Whitelist** tab.
3. Click **Add IP Address**.
4. Enter an **IP Address** in IPv4 or IPv6 format, or a **CIDR range** (e.g., `10.42.0.0/16`, `2001:db8::/32`).
5. Optionally add a **Description**.
6. Click **Add**.

:::note
Broad CIDR ranges — anything wider than `/16` for IPv4 or `/32` for IPv6, including `0.0.0.0/0` and `::/0` — are
rejected by default. On testnet only, an operator can set `INSECURE_M2M_ALLOW_ANY_IP_ENABLED=true` to permit allow-all
entries; add both `0.0.0.0/0` and `::/0` to allow every client (one covers IPv4, the other IPv6). Never enable this on
mainnet. The flag relaxes this create-time validation only — IP matching always runs, so an allow-all entry accepts
API-key requests from every source IP.
:::

### Overbroad entry warnings

The admin panel flags overbroad entries per application. The **IP Whitelist** tab marks each overbroad entry with an
"Allows any IP" badge and shows a warning callout while any such entry exists. The M2M applications list shows the same
badge next to affected apps. Remove or tighten the flagged entries to restore IP restrictions.

### Remove an IP Address

1. Find the IP address in the list.
2. Click **Remove**.
3. Confirm the action.

## Organizations

M2M applications can be linked to one or more organizations. Linked organizations determine which users and wallets the
M2M app can act on behalf of when using organization-scoped system permissions such as `m2m_org_rpc_access`,
`m2m_org_users_manage`, and `m2m_org_wallets_manage`.

### Link an organization

1. Open an M2M application.
2. Go to the **Organizations** tab.
3. Click **Add Organization**.
4. Search for the organization by name.
5. Click the organization row to link it.

### Remove a linked organization

1. Open an M2M application.
2. Go to the **Organizations** tab.
3. Find the organization in the list.
4. Click **Remove**.
5. Confirm the action.

## Org-owned credentials

:::note
Org-owned credentials require `MULTI_ORG_ENABLED=true`.
:::

Organization admins can create M2M credentials that belong to their own organization, managed from the organization's
admin panel. These are distinct from the zone-level credentials above, which an operator owns and links to
organizations: a zone-level credential is read-only to org admins, while an org-owned credential is fully theirs to
create, update, and delete.

| Property             | Zone-level credential                  | Org-owned credential                   |
| -------------------- | -------------------------------------- | -------------------------------------- |
| Created by           | Zone operator                          | Org admin                              |
| Visible to           | Organizations the operator links it to | The owning organization only           |
| Roles                | Any zone or org roles                  | Org roles within the org-admin ceiling |
| Managed by org admin | Read-only                              | Full create / update / delete          |

### List credentials visible to an organization

```
GET /api/organizations/:id/m2m-applications
```

Returns both org-owned credentials and the zone-level credentials the operator assigned to the org. Zone-level
credentials have `organizationId: null`; org-owned credentials carry the organization's ID.

### Create an org-owned credential

```
POST /api/organizations/:id/m2m-applications
```

Request body:

```json
{
  "name": "billing-bot",
  "description": "optional description",
  "roles": [{ "roleName": "org-role-name" }]
}
```

Roles must belong to the organization: zone-level, peer-org, or nonexistent role names all return `404 Not Found`
without disclosing which. A role that exists in the org but grants permissions beyond the org-admin ceiling (anything
other than `org_users_manage`, `org_wallets_manage`, or `org_rpc_access`) is rejected with `400 Bad Request`.

### Update an org-owned credential

```
PUT /api/organizations/:id/m2m-applications/:appId
```

The request body has the same shape as create, and roles are validated against the same ceiling. Only org-owned
credentials respond to this route; zone-level credentials assigned to the org return `404 Not Found`.

### Delete an org-owned credential

```
DELETE /api/organizations/:id/m2m-applications/:appId
```

Only org-owned credentials can be deleted. Zone-level credentials return `404 Not Found`.

## Organization User Management

M2M applications linked to organizations can programmatically manage users and wallets within those organizations. These
capabilities are controlled by system permissions assigned to the M2M app's role.

### `org_users_manage`

Allows the M2M app to create and list users within its linked organizations. Users created this way are automatically
assigned the organization's default roles.

### `org_wallets_manage`

Allows the M2M app to attach wallet addresses to users in its linked organizations. All wallet addresses must be fresh
EOAs: not already registered in the system, with nonce 0, and not a smart contract.

Creating a user with wallet addresses in a single request requires both `org_users_manage` and `org_wallets_manage`.

## Organization-Scoped RPC Access

M2M applications can be linked to organizations and granted the `org_rpc_access` system permission, allowing them to
make RPC calls on behalf of organization users. The authorization model differs between contract calls and event
queries:

### Contract reads (`eth_call`, `eth_estimateGas`)

When the M2M app makes a read call with a `from` address:

1. The system verifies the M2M app has `org_rpc_access`.
2. It looks up the user who owns the `from` wallet within the app's linked organizations.
3. It checks that user's **own roles** against the contract's function permission.

The M2M app's roles are not used for this check. The individual user must hold the required role for `checkRole`
permissions to pass.

### Contract writes (`eth_sendRawTransaction`)

When the M2M app submits a signed transaction:

1. The signer address is recovered from the raw transaction.
2. The same authorization flow as contract reads applies: the system verifies `org_rpc_access`, looks up the signer
   within linked organizations, and checks that user's roles against the contract's function permission with **write**
   access.
3. Transfers to externally-owned accounts (EOAs) skip the permission check entirely.

### Contract deployment

Contract creation (a transaction with no `to` address) needs `contract_deployment` in addition to `org_rpc_access`, and
grants it in two places:

1. The M2M app's own roles must include `contract_deployment`.
2. The recovered signer must be a wallet of a user in a linked organization, and that user's roles must also include
   `contract_deployment`.

The API key alone is therefore not enough to deploy — the transaction must be signed by a wallet belonging to a
permitted user. The deployment is recorded against that user, while the audit log records the M2M app and the API key
used.

`eth_feeHistory` and `eth_estimateGas` for a creation call sit behind the same permission, so a missing grant surfaces
during fee estimation before the deployment transaction is submitted.

:::note
`contract_deployment` is not an org-admin grantable permission, so an org-owned credential cannot hold it. Deployment
requires a zone-level M2M application.
:::

### Event queries (`eth_getLogs`)

When the M2M app queries logs:

1. The system verifies the M2M app has `org_rpc_access`.
2. It collects all wallet addresses across all linked organizations.
3. It checks the **M2M app's roles** against event permissions.

Individual user roles are not consulted. The M2M app's roles act as a blanket for all organization users.

### Setup implications

* For contract method access: the M2M app needs a role with `org_rpc_access`, and each user it acts on behalf of needs a
  role that satisfies the contract's function permission (e.g., a role listed in a `checkRole` rule). These can be
  different roles.
* For event log access: assign the role only to the M2M app. Users do not need the role individually.

## Query Endpoints

M2M applications can read permission and contract metadata from Prividium through query endpoints under
`/m2m-app-queries`. These are intended for integrations like webhook services and indexers that need to verify user
access or fetch contract details without making full RPC calls. Endpoints that return a user's or a contract's data
each require a dedicated system permission.

All requests authenticate with the M2M app's API key in the `x-api-key` header and must originate from a whitelisted IP
address.

### Describe the calling application

`GET /m2m-app-queries/me`

Returns the M2M app that owns the API key, including its roles and their system permissions. Use it to confirm a key
works and to check what the app can access.

Requires no system permission. The response only describes the app holding the key.

Response:

```json
{
  "id": "Xq7mK2pRtV9wLc4nB8sYd",
  "name": "chain-indexer",
  "ownerOrganizationId": null,
  "roles": [
    {
      "id": "Hf3jN6uQzA1eGk5oW0rTm",
      "roleName": "indexer",
      "systemPermissions": ["full_read_access"],
      "isSystemRole": false,
      "organizationId": null
    }
  ]
}
```

`ownerOrganizationId` is `null` for a zone-level app and holds the owning organization's ID for an organization app.

### Check user read access

`POST /m2m-app-queries/check-user-read-access`

Returns whether a given user has full read access to chain data. Useful before registering or firing a webhook on behalf
of that user.

Requires the `check_user_read_access` system permission on one of the M2M app's roles.

Request body:

```json
{ "userId": "usr_..." }
```

Response:

```json
{ "authorized": true }
```

`authorized` is `true` when the user has the `admin` role or the `full_read_access` system permission, and `false`
otherwise. Returns `404` if the user does not exist.

### Read contract metadata

`GET /m2m-app-queries/contracts/:contractAddress`

Returns the full contract record (address, name, description, ABI, disclosed addresses, template, disclosure flags) for
a registered contract.

Requires the `contract_metadata_read` system permission on one of the M2M app's roles. Returns `404` if no contract is
registered at the given address.

## How M2M Applications Differ From Other App Types

### Compared to OAuth Applications

M2M applications do not have:

* OAuth client IDs
* redirect URIs
* whitelisted browser origins
* user-facing login flows
* a public key field in the admin UI

OAuth applications are for end-user authentication. M2M applications are for machine principals.

### Compared to Tenants

M2M applications do not:

* create or manage users
* assign default roles to tenant-created users
* aggregate visibility across a tenant's managed users

Tenants model third-party user-management systems. M2M applications model machine principals with roles. Over time, M2M
applications are expected to replace tenant-based setups for machine-only integrations.
