> For the complete documentation index, see [llms.txt](https://docs.inrupt.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.inrupt.com/ess/3.0/services/service-platform-management/platform-management-api.md).

# Platform Management API

{% hint style="success" %}
Added in version 2.6.0
{% endhint %}

The Platform Management service enables provisioning of user accounts and resources before users access the system via the Admin API. Access to the Admin API is only permitted through a Service Account. The API provides secure, phased provisioning of WebIDs and Storage containers with proper access control throughout the process.

## Critical Security Requirements

{% hint style="danger" %}
**Username Binding Security**

The Platform Management service hosts an Admin API that can be integrated with a backend user provisioning system to set up users on ESS. The binding between ESS and users in the Identity Provider (IdP) is the **username**.

**It is vital that accounts with the same username are created in the IdP BEFORE calling the Admin API.** Failing to do this could allow a malicious user to claim the same username assigned for someone else, leading to unauthorized access to resources intended for another user.

Always ensure proper coordination between IdP account creation and ESS provisioning operations.
{% endhint %}

### Provisioning Workflow Scenarios

Depending on your organization's processes, the Platform Management API supports several provisioning workflows:

1. **Existing IdP Users**: Users already have accounts in the IdP, and the organization provisions ESS resources for these existing users
2. **User Self-Registration**: A user creates an account in the IdP first, then the organization provisions ESS resources for that user
3. **Organization-Managed**: The organization creates both the IdP account and ESS resources for new users in a coordinated process

In all scenarios, the IdP account with the target username **must exist before** calling the Admin API provisioning endpoints.

## Service Accounts

The Platform Management service APIs are accessible only through Service Accounts. A Service Account is a specialized account type with restricted privileges:

* **Provisioning Access**: Can call `/admin/provision` endpoints to create user accounts
* **No Personal Storage**: Service Accounts do not have their own storage containers
* **Read-Only WebID**: Service Account WebID documents are read-only and cannot be modified
* **Limited Scope**: Cannot issue Access Credentials on behalf of themselves
* **Temporary Elevated Access**: During setup phase, granted privileges to work on users' behalf
* **Automatic Revocation**: All elevated privileges are removed when accounts are activated

### Initial Service Account

Following installation of ESS the Platform Management service will automatically create a single Service Account at startup, using the name specified in the `INRUPT_PLATFORM_ACCOUNT_PROVISION_SERVICE_USERNAME` environment variable, if this account does not exist. Once created, the username cannot be changed and the Service Account cannot be removed.

On startup, the Platform Management service will automatically create a single Service Account using the specified username, if this account does not exist. Once created, the username cannot be changed and the Service Account cannot be removed.

If the `INRUPT_PLATFORM_ACCOUNT_PROVISION_SERVICE_USERNAME` environment variable is not set, the service will fail to start.

The initial Service Account is granted specific permissions to provision endpoints and serves as the foundation for all platform provisioning operations.

### Service Account Configuration

The initial Service Account is configured via environment variables:

```bash
INRUPT_PLATFORM_ACCOUNT_PROVISION_SERVICE_USERNAME=provision-service
```

{% hint style="danger" %}
**Critical Security Requirement**

The Service Account credentials have administrative privileges to modify ESS user accounts and resources. Access to this account must be strictly governed.

Ensure proper security controls are in place for the Service Account in your IdP configuration.
{% endhint %}

## Provisioning Overview

The Platform Management service implements a two-phase provisioning lifecycle:

1. **Setup Phase**: Service Account creates and configures user resources
2. **Active Phase**: Resources are transferred to user ownership and Service Account privileges are revoked

### Service Account Privileges During Setup

When a provisioning session is in **setup** state, the Service Account is granted temporary elevated privileges to work on the user's behalf:

* **Storage Operations**: Create containers, upload files, ingest data into Storage created for the user, and manage resources
* **Access Credential Issuance**: Issue Access Grants on behalf of the user for third parties to access user resources
* **WebID Management**: Read and update WebID documents on user's behalf

### Privilege Revocation on Activation

When `PUT /admin/provision/{accountId}/activate` is called:

* **Immediate Revocation**: Service Account loses all elevated privileges instantly
* **User Ownership**: Resources are transferred to end user control
* **Access Lockout**: Service Account can no longer access activated user resources
* **Atomic Transition**: No gap between privilege revocation and user ownership

This ensures proper security boundaries between administrative provisioning and user ownership.

## Platform Management Endpoints

By default, the Platform Management service runs from the following root URL:

```
https://platform.<ESS Domain>
```

The Platform Management service Admin API consists of the following endpoints:

| Endpoint                                        | Description                                       |
| ----------------------------------------------- | ------------------------------------------------- |
| **`POST /admin/provision`**                     | Create a new user provisioning account            |
| **`GET /admin/provision/{accountId}`**          | Get status of a provisioning account              |
| **`PUT /admin/provision/{accountId}/webid`**    | Add a WebID to a provisioning account             |
| **`PUT /admin/provision/{accountId}/storage`**  | Add a storage container to a provisioning account |
| **`PUT /admin/provision/{accountId}/identity`** | Set identity mappings for a provisioning account  |
| **`PUT /admin/provision/{accountId}/activate`** | Activate account and transfer ownership to user   |
| **`DELETE /admin/provision/{accountId}`**       | Deprovision resources (setup state only)          |
| **`GET /user/account`**                         | Get the authenticated user's account details      |
| **`POST /user/account`**                        | Create a new user account (self-service)          |
| **`PUT /user/account/webid`**                   | Add a WebID to the authenticated user's account   |
| **`PUT /user/account/storage`**                 | Add storage to the authenticated user's account   |

## Create Provisioning Account

Create a new user account in setup state. WebID and storage must be added separately using the dedicated endpoints.

### Input

| Endpoint      | **`https://platform.{ESS Domain}/admin/provision`**                                     |
| ------------- | --------------------------------------------------------------------------------------- |
| Method        | **`POST`**                                                                              |
| Authorization | An access token for a Service Account that has write access to the provision endpoints. |
| Content-Type  | **`application/json`**                                                                  |
| Payload       | A JSON object containing user data and optional proof for compliance purposes.          |

The provisioning request payload is represented as JSON:

```json
{
  "userData": {
    "username": "<username>"
  },
  "proof": "<compliance proof data>"
}
```

### Request Validation Rules

* The **`userData`** field must be present
* The **`userData.username`** field must be present and non-empty
* The **`proof`** field is optional but recommended for compliance workflows. This field can contain any compliance-related evidence (consent forms, legal documents, etc.) and is stored opaquely by the service for audit purposes.

{% hint style="warning" %}
**Security Prerequisite**

Before calling this endpoint, ensure that an account with the specified username already exists in your Identity Provider (IdP). The username serves as the binding between ESS and the IdP user account. Provisioning without a corresponding IdP account creates a security vulnerability where malicious users could claim the username.
{% endhint %}

### Example Request

```http
POST /admin/provision HTTP/1.1
Host: platform.example.com
Authorization: DPoP <dpop-bound-jwt>
DPoP: <proof-of-possession-token>
Content-Type: application/json

{
  "userData": {
    "username": "johndoe"
  },
  "proof": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
```

### Output

Creates a new user account in setup state. The response includes the account ID, agent identifier, and initial (empty) WebID and storage arrays. Returns `201` for newly created accounts or `200` if the account already exists.

### Example Response

```http
HTTP/1.1 201 Created
Content-Type: application/json

{
  "id": "01JXYZ1234ABCDEF5678GHIJ90",
  "agent": "urn:ess:agent:01JXYZ1234ABCDEF5678GHIJ90",
  "state": "setup",
  "webid": [],
  "storage": [],
  "createdAt": "2025-01-15T10:30:00Z",
  "proof": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "identityMappings": [
    {
      "type": "oauth",
      "issuer": "https://your-idp.example.com",
      "subject": "johndoe",
      "createdAt": "2025-01-15T10:30:00Z"
    }
  ]
}
```

## Add WebID

Add a WebID to an existing provisioning account in setup state.

### Input

| Field         | Value                                                                                   |
| ------------- | --------------------------------------------------------------------------------------- |
| Endpoint      | **`https://platform.{ESS Domain}/admin/provision/{accountId}/webid`**                   |
| Method        | **`PUT`**                                                                               |
| Authorization | An access token for a Service Account that has write access to the provision endpoints. |

### Example Request

```http
PUT /admin/provision/01JXYZ1234ABCDEF5678GHIJ90/webid HTTP/1.1
Host: platform.example.com
Authorization: DPoP xxxxxxxx
DPoP: <proof-of-possession-token>
```

### Example Response

```http
HTTP/1.1 201 Created
Content-Type: application/json

{
  "id": "01JXYZ1234ABCDEF5678GHIJ90",
  "agent": "urn:ess:agent:01JXYZ1234ABCDEF5678GHIJ90",
  "state": "setup",
  "webid": [
    "https://id.example.com/johndoe"
  ],
  "storage": [],
  "createdAt": "2025-01-15T10:30:00Z",
  "proof": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "identityMappings": [...]
}
```

#### Error Responses

| Status    | Description                     |
| --------- | ------------------------------- |
| **`400`** | Account is not in setup state   |
| **`404`** | Provisioning account not found  |
| **`405`** | WebID service is not configured |

## Add Storage Container

Add a storage container to an existing provisioning account in setup state.

### Input

| Field         | Value                                                                                   |
| ------------- | --------------------------------------------------------------------------------------- |
| Endpoint      | **`https://platform.{ESS Domain}/admin/provision/{accountId}/storage`**                 |
| Method        | **`PUT`**                                                                               |
| Authorization | An access token for a Service Account that has write access to the provision endpoints. |

### Example Request

```http
PUT /admin/provision/01JXYZ1234ABCDEF5678GHIJ90/storage HTTP/1.1
Host: platform.example.com
Authorization: DPoP xxxxxxxx
DPoP: <proof-of-possession-token>
```

### Output

Returns the updated provisioning account with the new storage container added.

### Example Response

```http
HTTP/1.1 201 Created
Content-Type: application/json

{
  "id": "01JXYZ1234ABCDEF5678GHIJ90",
  "agent": "urn:ess:agent:01JXYZ1234ABCDEF5678GHIJ90",
  "state": "setup",
  "webid": [
    "https://id.example.com/johndoe"
  ],
  "storage": [
    "https://storage.example.com/01JXYZ1234ABCDEF5678GHIJ90/sp/"
  ],
  "createdAt": "2025-01-15T10:30:00Z",
  "proof": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "identityMappings": [...]
}
```

#### Error Responses

| Status    | Description                                              |
| --------- | -------------------------------------------------------- |
| **`400`** | Account is not in setup state, or storage limit exceeded |
| **`404`** | Provisioning account not found                           |

{% hint style="info" %}
**Storage Limits**

By default, each provisioning account is limited to 10 storage containers. Attempting to exceed this limit will result in a 400 Bad Request response. This limit can be modified via configuration.
{% endhint %}

## Set Identity Mappings

Set the identity mappings for a provisioning account. This replaces all existing identity mappings with the provided set. Identity mappings bind external Identity Provider identities to this ESS account.

### Input

| Field         | Value                                                                                   |
| ------------- | --------------------------------------------------------------------------------------- |
| Endpoint      | **`https://platform.{ESS Domain}/admin/provision/{accountId}/identity`**                |
| Method        | **`PUT`**                                                                               |
| Authorization | An access token for a Service Account that has write access to the provision endpoints. |
| Content-Type  | **`application/json`**                                                                  |
| Payload       | An array of identity mapping objects.                                                   |

### Request Body

```json
[
  {
    "type": "oauth",
    "issuer": "https://login.example.com",
    "subject": "user-subject-from-idp"
  }
]
```

| Field         | Required | Description                     |
| ------------- | -------- | ------------------------------- |
| **`type`**    | Yes      | Mapping type (e.g., `oauth`)    |
| **`issuer`**  | Yes      | Identity Provider issuer URL    |
| **`subject`** | Yes      | Subject identifier from the IdP |

### Example Request

```http
PUT /admin/provision/01JXYZ1234ABCDEF5678GHIJ90/identity HTTP/1.1
Host: platform.example.com
Authorization: DPoP xxxxxxxx
DPoP: <proof-of-possession-token>
Content-Type: application/json

[
  {
    "type": "oauth",
    "issuer": "https://login.example.com",
    "subject": "auth0|abc123def456"
  }
]
```

### Example Response

```http
HTTP/1.1 200 OK
Content-Type: application/json

{
  "id": "01JXYZ1234ABCDEF5678GHIJ90",
  "agent": "urn:ess:agent:01JXYZ1234ABCDEF5678GHIJ90",
  "state": "setup",
  "webid": [
    "https://id.example.com/johndoe"
  ],
  "storage": [],
  "createdAt": "2025-01-15T10:30:00Z",
  "proof": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "identityMappings": [
    {
      "type": "oauth",
      "issuer": "https://login.example.com",
      "subject": "auth0|abc123def456",
      "createdAt": "2025-01-15T10:35:00Z"
    }
  ]
}
```

#### Error Responses

| Status    | Description                                            |
| --------- | ------------------------------------------------------ |
| **`400`** | Account is not in setup state, or invalid mapping type |
| **`404`** | Provisioning account not found                         |
| **`409`** | Mapping already exists for a different account         |

## Get Provisioning Status

Retrieve the current status and details of a provisioning account. Returns `404` for deprovisioned accounts.

### Input

| Field         | Value                                                                                  |
| ------------- | -------------------------------------------------------------------------------------- |
| Endpoint      | **`https://platform.{ESS Domain}/admin/provision/{accountId}`**                        |
| Method        | **`GET`**                                                                              |
| Authorization | An access token for a Service Account that has read access to the provision endpoints. |

### Example Request

```http
GET /admin/provision/01JXYZ1234ABCDEF5678GHIJ90 HTTP/1.1
Host: platform.example.com
Authorization: DPoP xxxxxxxx
DPoP: <proof-of-possession-token>
```

### Example Response

```http
HTTP/1.1 200 OK
Content-Type: application/json

{
  "id": "01JXYZ1234ABCDEF5678GHIJ90",
  "agent": "urn:ess:agent:01JXYZ1234ABCDEF5678GHIJ90",
  "state": "setup",
  "webid": [
    "https://id.example.com/johndoe"
  ],
  "storage": [
    "https://storage.example.com/01JXYZ1234ABCDEF5678GHIJ90/sp/"
  ],
  "createdAt": "2025-01-15T10:30:00Z",
  "proof": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "identityMappings": [
    {
      "type": "oauth",
      "issuer": "https://your-idp.example.com",
      "subject": "johndoe",
      "createdAt": "2025-01-15T10:30:00Z"
    }
  ]
}
```

## Activate Provisioning Account

Activate a provisioning account, transferring ownership from Service Account to the end user. This immediately revokes all Service Account privileges for the resources.

### Input

| Field         | Value                                                                                   |
| ------------- | --------------------------------------------------------------------------------------- |
| Endpoint      | **`https://platform.{ESS Domain}/admin/provision/{accountId}/activate`**                |
| Method        | **`PUT`**                                                                               |
| Authorization | An access token for a Service Account that has write access to the provision endpoints. |

### Example Request

```http
PUT /admin/provision/01JXYZ1234ABCDEF5678GHIJ90/activate HTTP/1.1
Host: platform.example.com
Authorization: DPoP xxxxxxxx
DPoP: <proof-of-possession-token>
```

### Example Response

```http
HTTP/1.1 200 OK
Content-Type: application/json

{
  "id": "01JXYZ1234ABCDEF5678GHIJ90",
  "agent": "urn:ess:agent:01JXYZ1234ABCDEF5678GHIJ90",
  "state": "active",
  "webid": [
    "https://id.example.com/johndoe"
  ],
  "storage": [
    "https://storage.example.com/01JXYZ1234ABCDEF5678GHIJ90/sp/"
  ],
  "createdAt": "2025-01-15T10:30:00Z",
  "proof": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "identityMappings": [...]
}
```

{% hint style="info" %}
**Note**

Activation is **atomic and irreversible**. Once activated:

* Service Account immediately loses all access to user resources
* Resources cannot return to setup state
* Additional storage cannot be added via admin API
* Only the end user can access their resources, as well as third-party agents for which Access Grants have been issued during provisioning
  {% endhint %}

## Deprovision Resources

Remove a provisioning account and all associated resources. Only available for accounts in setup state. This endpoint is idempotent — calling it on an already deprovisioned account returns `204`.

### Input

| Field         | Value                                                                                   |
| ------------- | --------------------------------------------------------------------------------------- |
| Endpoint      | **`https://platform.{ESS Domain}/admin/provision/{accountId}`**                         |
| Method        | **`DELETE`**                                                                            |
| Authorization | An access token for a Service Account that has write access to the provision endpoints. |

### Example Request

```http
DELETE /admin/provision/01JXYZ1234ABCDEF5678GHIJ90 HTTP/1.1
Host: platform.example.com
Authorization: DPoP xxxxxxxx
DPoP: <proof-of-possession-token>
```

### Output

Returns 204 No Content on successful deprovisioning.

### Example Response

```http
HTTP/1.1 204 No Content
```

{% hint style="warning" %}
**Important Prerequisites for Deprovisioning**

Before deprovisioning a non-active account, ensure that:

* All Storage resources created during setup are deleted
* All Access Credentials issued on behalf of the user are revoked

Deprovisioning permanently deletes the WebID, storage containers, and all associated data. This operation cannot be undone and is only available for sessions in setup state.
{% endhint %}

## Error Responses

The Platform Management API uses standard HTTP status codes and RFC 7807 Problem Details format for error responses.

### Common Error Responses

**401 Unauthorized**

```json
{
  "title": "Unauthorized",
  "status": 401,
  "detail": "Valid authentication required"
}
```

**403 Forbidden**

```json
{
  "title": "Forbidden",
  "status": 403,
  "detail": "Service Account not authorized for admin operations"
}
```

**400 Bad Request - Invalid Input**

```json
{
  "title": "Bad Request",
  "status": 400,
  "violations": [
    {
      "field": "userData.username",
      "message": "Username cannot be empty"
    }
  ]
}
```

**400 Bad Request - Storage Limit**

```json
{
  "title": "Bad Request",
  "status": 400,
  "detail": "Storage limit exceeded. Maximum allowed: 10"
}
```

**400 Bad Request - Invalid State Transition**

```json
{
  "title": "Bad Request", 
  "status": 400,
  "detail": "Cannot add storage to account in state: ACTIVE"
}
```

## Service Account Access During Setup Phase

While resources are in setup state, Service Accounts have elevated privileges to perform operations on behalf of users:

### Storage Operations

Service Accounts can create containers, upload files, and manage permissions:

```http
PUT https://storage.example.com/01JXYZ1234ABCDEF5678GHIJ90/sp/document.ttl
Authorization: DPoP <service-account-token>
DPoP: <proof-of-possession-token>
Content-Type: text/turtle

<> a <http://example.org/Document> ;
   <http://example.org/createdBy> "service-account" .
```

### WebID Management

Service Accounts can read and update WebID documents:

```http
PUT https://id.example.com/johndoe
Authorization: DPoP <service-account-token>
DPoP: <proof-of-possession-token>
```

### Access Credential Issuance

Service Accounts can issue Access Credentials on behalf of users during the setup phase, allowing third parties to access user resources according to specified permissions. When issuing credentials, the `credential.credentialSubject.id` must be set to the user's WebID:

```http
POST https://accessgrant.example.com/issue
Authorization: DPoP <service-account-token>
DPoP: <proof-of-possession-token>
Content-Type: application/json

{
  "credential": {
    "@context": [
      "https://www.w3.org/2018/credentials/v1",
      "https://schema.inrupt.com/credentials/v1.jsonld"
    ],
    "type": ["VerifiableCredential"],
    "credentialSubject": {
      "id": "https://id.example.com/johndoe",
      "hasConsent": [{
        "mode": ["http://www.w3.org/ns/auth/acl#Read"],
        "forPersonalData": [
          "https://storage.example.com/01JXYZ1234ABCDEF5678GHIJ90/sp/foo/bar"
        ],
        "isConsentForDataSubject": "https://id.example.com/johndoe",
        "hasStatus": "https://w3id.org/GConsent#ConsentStatusRequested",
        "forPurpose": "https://example.com/SpecificPurpose"
      }]
    }
  }
}
```

## Complete Provisioning Workflow

Here's a complete example of provisioning a user account:

### Step 1: Create Account

```http
POST /admin/provision
{
  "userData": {
    "username": "johndoe"
  },
  "proof": "compliance-proof-data"
}
```

Response: Account created in setup state.

### Step 2: Add WebID

```http
PUT /admin/provision/01JXYZ1234ABCDEF5678GHIJ90/webid
```

Response: WebID added to account.

### Step 3: Add Storage

```http
PUT /admin/provision/01JXYZ1234ABCDEF5678GHIJ90/storage
```

Response: Storage container added to account.

### Step 4: Configure Resources

Service Account can now access and configure user resources:

* Create containers in storage
* Upload initial data
* Configure WebID profile
* Issue Access Credentials for third parties

### Step 5: Activate Account

```http
PUT /admin/provision/01JXYZ1234ABCDEF5678GHIJ90/activate
```

Response: Account activated, Service Account access revoked, user gains full control.

## Configuration

The Platform Management service requires several configuration options for proper operation.

### Required Configuration

#### INRUPT\_PLATFORM\_HTTP\_BASE\_URL

The base URL for the Platform Management service HTTP endpoints.

```bash
INRUPT_PLATFORM_HTTP_BASE_URL=https://platform.{ESS_DOMAIN}
```

#### INRUPT\_PLATFORM\_ACCOUNT\_PROVISION\_SERVICE\_USERNAME

**Required.** Username for the initial Service Account. The service will automatically create this Service Account on startup if it does not already exist. Once created, the username cannot be changed. If not set, the service will fail to start.

```bash
INRUPT_PLATFORM_ACCOUNT_PROVISION_SERVICE_USERNAME=provision-service
```

### Optional Configuration

#### INRUPT\_PLATFORM\_STORAGE\_MAX\_LIMIT

Maximum number of storage containers allowed per provisioning session.

**Default**: `10`

```bash
INRUPT_PLATFORM_STORAGE_MAX_LIMIT=10
```

{% hint style="warning" %}
**Important: Storage Limit Consistency**

This value must be set to the same value as:

* `INRUPT_STORAGE_MAX_PODS_PER_OWNER`
* `INRUPT_AUTHORIZATION_MAX_POD_COUNT`

Eventually, `INRUPT_PLATFORM_STORAGE_MAX_LIMIT` will be the primary configuration option, with the others retained for backwards compatibility only.
{% endhint %}

#### INRUPT\_AUTHORIZATION\_RELATIONSHIP\_RETENTION\_WINDOW\_ENABLED

Controls whether the relationship cleanup task is enabled for removing soft-deleted relationships.

**Default**: `true`

```bash
INRUPT_AUTHORIZATION_RELATIONSHIP_RETENTION_WINDOW_ENABLED=true
```

#### INRUPT\_AUTHORIZATION\_RELATIONSHIP\_RETENTION\_WINDOW\_DURATION

Duration to retain soft-deleted relationships before permanent deletion. Uses ISO 8601 duration format.

**Default**: `P30D` (30 days)

```bash
INRUPT_AUTHORIZATION_RELATIONSHIP_RETENTION_WINDOW_DURATION=P30D
```

#### INRUPT\_AUTHORIZATION\_RELATIONSHIP\_RETENTION\_WINDOW\_BATCH\_SIZE

Maximum number of relationships to delete per batch operation. Must be greater than 0.

**Default**: `500`

```bash
INRUPT_AUTHORIZATION_RELATIONSHIP_RETENTION_WINDOW_BATCH_SIZE=500
```

#### INRUPT\_AUTHORIZATION\_RELATIONSHIP\_RETENTION\_WINDOW\_TASK\_EVERY

Duration between cleanup task executions. Uses ISO 8601 duration format.

**Default**: `PT6H` (every 6 hours)

```bash
INRUPT_AUTHORIZATION_RELATIONSHIP_RETENTION_WINDOW_TASK_EVERY=PT6H
```

## Audit Events

The Platform Management service emits comprehensive audit events for all administrative operations to ensure compliance and accountability. These events are sent to the Audit service and contain detailed information about the actions performed by Service Accounts.

### Event Types

#### Account Created Event

**Event Name**: `admin-account-created`\
**Event Type**: `Create`\
**Description**: Fired when a Service Account creates a new provisioning session

**Event Details**:

* **Actor**: Service Account WebID performing the operation
* **Attributed To**: End user's WebID (account being created)
* **Object**: Provisioning session URI, WebID document, and storage containers
* **Instrument**: Compliance proof data (if provided)
* **Result**: Success status and account state information

#### Account Activated Event

**Event Name**: `admin-account-activated`\
**Event Type**: `Update`\
**Description**: Fired when a Service Account activates a provisioning session, transferring ownership to the end user

**Event Details**:

* **Actor**: Service Account WebID performing the operation
* **Attributed To**: End user's WebID (account being activated)
* **Object**: Provisioning session URI, WebID document, and storage containers
* **Instrument**: Compliance proof data
* **Result**: Success status with confirmation that admin access was removed

#### Account Deprovisioned Event

**Event Name**: `admin-account-deprovisioned`\
**Event Type**: `Delete`\
**Description**: Fired when a Service Account deprovisions a session and removes all associated resources

**Event Details**:

* **Actor**: Service Account WebID performing the operation
* **Attributed To**: End user's WebID (account being deprovisioned)
* **Object**: Provisioning session URI, WebID document, and storage containers
* **Instrument**: Compliance proof data
* **Result**: Success status with confirmation that all resources were removed

### Audit Event Structure

Each audit event includes the following standard components:

* **Actor**: The Service Account performing the administrative action
* **Attributed To**: The end user on whose behalf the action is performed
* **Object**: All affected resources (provisioning session, WebID, storage containers)
* **Instrument**: Any compliance proof or evidence associated with the operation
* **Result**: Operation outcome and relevant status information

### Example Audit Event

Here is an example of an `admin-account-created` audit event:

```json
{
  "@context": [
    "https://www.w3.org/ns/activitystreams",
    "https://schema.inrupt.com/audit/v1.jsonld"
  ],
  "id": "urn:uuid:85fcb915-29a4-4e0f-bf3a-27ed4c13f559",
  "type": [
    "Activity",
    "Create"
  ],
  "name": "admin-account-created",
  "summary": "Admin agent created account on behalf of user",
  "generator": {
    "wasAssociatedWith": "ess-platform-management-7fccddb8bf-2rssk",
    "type": [
      "SoftwareApplication"
    ],
    "qualifiedAssociation": "79",
    "name": "inrupt-platform-management-postgres",
    "id": "https://platform.example.com/"
  },
  "actor": [
    {
      "id": "https://id.example.com/service-account"
    }
  ],
  "attributedTo": [
    {
      "id": "https://id.example.com/johndoe",
      "name": "johndoe"
    }
  ],
  "object": [
    {
      "type": [
        "object"
      ],
      "content": "account_id=01JXYZ1234ABCDEF5678GHIJ90,state=setup",
      "id": "https://platform.example.com/admin/provision/01JXYZ1234ABCDEF5678GHIJ90",
      "name": "johndoe"
    },
    {
      "id": "https://id.example.com/johndoe",
      "type": [
        "WebID"
      ],
      "name": "WebID Document"
    }
  ],
  "instrument": [
    {
      "name": "Account Provision Proof",
      "content": "compliance-proof-data"
    }
  ],
  "result": [
    {
      "content": "status=success",
      "type": [
        "object"
      ],
      "name": "Provisioning Result"
    }
  ],
  "identifier": "93c270cbbc9a8fa9c413210ba028e03d",
  "published": "2025-01-15T10:30:00Z"
}
```

This example shows:

* **Actor**: The Service Account (`https://id.example.com/service-account`) performing the operation
* **Attributed To**: The end user (`https://id.example.com/johndoe`) on whose behalf the account is created
* **Object**: The provisioning session and WebID document that were created
* **Instrument**: The compliance proof provided during account creation
* **Result**: Success status of the provisioning operation

### Additional Service Audit Events

Other ESS services (Storage and Access Grant Services) will emit their existing audit events to record Service Account actions during the provisioning process. This provides comprehensive audit coverage across all system components:

* **Storage Service Events**: Record storage container creation, data ingestion, and resource management performed by Service Accounts
* **Access Grant Service Events**: Record credential issuance and Access Grant operations performed on behalf of users
* **Authorization Service Events**: Record permission changes and access control updates during setup and activation phases

### Compliance Integration

Audit events support compliance workflows by:

* Recording all administrative actions with timestamps
* Tracking the delegation relationship between Service Accounts and end users
* Including compliance proof data in event records
* Providing clear attribution and accountability trails
* Supporting regulatory requirements for data handling and user consent
* Providing comprehensive audit coverage across all ESS services involved in provisioning

These audit events can be consumed by compliance monitoring systems, SIEM platforms, or other audit log aggregation tools to maintain comprehensive records of all Platform Management operations and related service activities.

## User Account Endpoints

{% hint style="success" %}
Added in version 3.0.0
{% endhint %}

User account endpoints provide self-service account management for authenticated users. Users authenticate with their Identity Provider, exchange the IdP token for an ESS Access Token via the [token exchange endpoint](/ess/3.0/services/service-platform-management/token-exchange.md), and use that token to manage their own account.

### Get User Account

Retrieve the authenticated user's account details. The user's identity is determined from the ESS Access Token (issuer + subject claims).

| Field         | Value                                            |
| ------------- | ------------------------------------------------ |
| Endpoint      | **`https://platform.{ESS Domain}/user/account`** |
| Method        | **`GET`**                                        |
| Authorization | ESS Access Token                                 |

#### Example Request

```http
GET /user/account HTTP/1.1
Host: platform.example.com
Authorization: Bearer <ess-access-token>
```

#### Example Response

```http
HTTP/1.1 200 OK
Content-Type: application/json

{
  "id": "01JXYZ1234ABCDEF5678GHIJ90",
  "agent": "urn:ess:agent:01JXYZ1234ABCDEF5678GHIJ90",
  "state": "active",
  "webid": [
    "https://id.example.com/johndoe"
  ],
  "storage": [
    "https://storage.example.com/01JXYZ1234ABCDEF5678GHIJ90/sp/"
  ],
  "createdAt": "2025-01-15T10:30:00Z",
  "identityMappings": [
    {
      "type": "oauth",
      "issuer": "https://login.example.com",
      "subject": "user-subject-id",
      "createdAt": "2025-01-15T10:30:00Z"
    }
  ]
}
```

#### Error Responses

| Status    | Description                        |
| --------- | ---------------------------------- |
| **`404`** | No account found for this identity |
| **`401`** | Not authenticated                  |

### Create User Account

Create a new account for the authenticated user. The identity mapping is automatically created from the ESS Access Token claims. Accounts are created in an active state.

This endpoint is idempotent — if an account already exists for the identity, the existing account is returned with a `200` status.

| Field         | Value                                            |
| ------------- | ------------------------------------------------ |
| Endpoint      | **`https://platform.{ESS Domain}/user/account`** |
| Method        | **`POST`**                                       |
| Authorization | ESS Access Token                                 |
| Content-Type  | **`application/json`**                           |

#### Request Body

```json
{
  "username": "<username>"
}
```

| Field          | Required | Description                                                                                                                                           |
| -------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`username`** | No       | Preferred username for the account. If provided, must be lowercase alphanumeric with hyphens, 1–63 characters (pattern: `^[a-z0-9][a-z0-9-]{0,62}$`). |

#### Example Response (Created)

```http
HTTP/1.1 201 Created
Content-Type: application/json

{
  "id": "01JXYZ1234ABCDEF5678GHIJ90",
  "agent": "urn:ess:agent:01JXYZ1234ABCDEF5678GHIJ90",
  "state": "active",
  "webid": [],
  "storage": [],
  "createdAt": "2025-01-15T10:30:00Z",
  "identityMappings": [
    {
      "type": "oauth",
      "issuer": "https://login.example.com",
      "subject": "user-subject-id",
      "createdAt": "2025-01-15T10:30:00Z"
    }
  ]
}
```

#### Error Responses

| Status    | Description                                 |
| --------- | ------------------------------------------- |
| **`400`** | Request is invalid                          |
| **`401`** | Not authenticated                           |
| **`403`** | Account is being set up by an administrator |
| **`409`** | Concurrent account creation detected        |

### Add WebID to User Account

Add a WebID to the authenticated user's account.

| Field         | Value                                                  |
| ------------- | ------------------------------------------------------ |
| Endpoint      | **`https://platform.{ESS Domain}/user/account/webid`** |
| Method        | **`PUT`**                                              |
| Authorization | ESS Access Token                                       |

#### Example Request

```http
PUT /user/account/webid HTTP/1.1
Host: platform.example.com
Authorization: Bearer <ess-access-token>
```

#### Example Response

```http
HTTP/1.1 201 Created
Content-Type: application/json

{
  "id": "01JXYZ1234ABCDEF5678GHIJ90",
  "agent": "urn:ess:agent:01JXYZ1234ABCDEF5678GHIJ90",
  "state": "active",
  "webid": [
    "https://id.example.com/johndoe"
  ],
  "storage": [],
  "createdAt": "2025-01-15T10:30:00Z",
  "identityMappings": [
    {
      "type": "oauth",
      "issuer": "https://login.example.com",
      "subject": "user-subject-id",
      "createdAt": "2025-01-15T10:30:00Z"
    }
  ]
}
```

#### Error Responses

| Status    | Description                                 |
| --------- | ------------------------------------------- |
| **`404`** | Account not found                           |
| **`401`** | Not authenticated                           |
| **`403`** | Account is being set up by an administrator |
| **`405`** | WebID service is not configured             |

### Add Storage to User Account

Add a storage container to the authenticated user's account. The account must have a WebID before storage can be added.

| Field         | Value                                                    |
| ------------- | -------------------------------------------------------- |
| Endpoint      | **`https://platform.{ESS Domain}/user/account/storage`** |
| Method        | **`PUT`**                                                |
| Authorization | ESS Access Token                                         |

#### Example Request

```http
PUT /user/account/storage HTTP/1.1
Host: platform.example.com
Authorization: Bearer <ess-access-token>
```

#### Example Response

```http
HTTP/1.1 201 Created
Content-Type: application/json

{
  "id": "01JXYZ1234ABCDEF5678GHIJ90",
  "agent": "urn:ess:agent:01JXYZ1234ABCDEF5678GHIJ90",
  "state": "active",
  "webid": [
    "https://id.example.com/johndoe"
  ],
  "storage": [
    "https://storage.example.com/01JXYZ1234ABCDEF5678GHIJ90/sp/"
  ],
  "createdAt": "2025-01-15T10:30:00Z",
  "identityMappings": [
    {
      "type": "oauth",
      "issuer": "https://login.example.com",
      "subject": "user-subject-id",
      "createdAt": "2025-01-15T10:30:00Z"
    }
  ]
}
```

#### Error Responses

| Status    | Description                                 |
| --------- | ------------------------------------------- |
| **`400`** | Account is missing a WebID                  |
| **`404`** | Account not found                           |
| **`401`** | Not authenticated                           |
| **`403`** | Account is being set up by an administrator |

## Additional Information

See also [Quarkus Configuration Options](https://quarkus.io/guides/all-config) for additional service configuration options.
