Skip to main content
Version: 0.4.0

Services API

The services API manages service instances — the configurations that connect the Reference Implementation to its dependent services (verifiable credential services, storage services, and identity resolver services).

Each service instance records which adapter to use, the connection details (base URL, API key, etc.), and whether the instance is the primary for its service type. The configuration is encrypted at rest and sensitive fields (such as API keys) are masked in API responses.

For background on how services fit into the architecture, see Service Architecture.

Interactive API documentation

The Reference Implementation includes a Swagger UI at /api-docs with full request/response schemas you can try directly from the browser. The endpoint descriptions below focus on behaviour and internal logic — refer to Swagger for exact payload shapes. All endpoints require authentication — see Authentication for how to obtain a Bearer token.

Concepts

Service Types and Adapter Types

Every service instance has a service type (what category of service it provides) and an adapter type (which specific implementation it uses). The supported service types and their available adapters are documented on the Service Architecture page.

Each adapter type has its own configuration schema. When creating or updating a service instance, the config object is validated against the adapter's schema before being encrypted and stored. See the adapter pages within each service for the configuration fields each adapter requires:

System Services vs Tenant Services

Service instances exist at two levels — system services (created during startup, owned by the system tenant, read-only defaults visible to all tenants) and tenant services (created through this API, scoped exclusively to the creating tenant). See System Services vs Tenant Services for details.

Primary Instances

Each tenant can designate one service instance per service type as the primary. The primary instance is used by default when other operations (such as DID creation or credential issuance) need a service of that type but no specific instance is specified.

When a service instance is created or updated with isPrimary: true, any existing primary for the same service type within the tenant is automatically demoted to isPrimary: false.

Configuration Encryption

Service configurations contain sensitive data (API keys, credentials). The config object is encrypted at rest and sensitive fields are masked in API responses.

Endpoints

Create a service instance

POST /api/v1/services

Registers a new service instance for the authenticated tenant. The config object is validated against the adapter's schema (see Service Types and Adapter Types above), encrypted, and stored.

serviceType, adapterType, name and config are required. name and description cannot be empty or contain only whitespace, and description is omitted rather than sent as null. config must be an object.


List service instances

GET /api/v1/services

Returns service instances for the authenticated tenant, including system defaults. Results are paginated and can be filtered by service type and adapter type.

ParameterTypeDefaultDescription
serviceTypestringAll typesFilter by service type. One of IDR, STORAGE, VC; any other value is rejected with a 400
adapterTypestringAll adaptersFilter by adapter type. One of VCKIT, PYX_IDR, UNCEFACT_STORAGE; any other value is rejected with a 400
limitintegerDefaults to 20, or the configured maximum when it is lowerA value above the maximum is rejected with a 400 that names the maximum
offsetinteger0Number of results to skip

Get a service instance

GET /api/v1/services/{id}

Retrieves a specific service instance by its database ID. The tenant can access instances they own and system defaults.


Update a service instance

PATCH /api/v1/services/{id}

Updates one or more fields of a service instance owned by the tenant. System defaults cannot be updated.

At least one of name, description, config, or isPrimary must be provided. A body with none of them, including one whose only keys are unrecognised, is rejected with a 400 rather than applied as a no-op. Sending description: null clears the description. Neither name nor description may be empty or contain only whitespace, and name cannot be cleared.

When config is provided, the new fields are merged with the existing configuration (shallow merge), the merged result is validated against the adapter's schema, and then encrypted before storage. This means you can update individual config fields without re-sending the entire config object.


Delete a service instance

DELETE /api/v1/services/{id}

Permanently deletes a service instance owned by the tenant. A system default is visible to the tenant (see Get a service instance), but deleting one is rejected with a 403 Forbidden, before any reference check runs.

If the caller's own DIDs, registrars, or identifier schemes reference the instance, the request is rejected with a 409 Conflict unless force=true is set. The counts in the response cover only the caller's own referencing records. When forced, the foreign keys on referencing records are set to null.

This check does not cover render templates. A render template can store a storage service instance ID for the credentials it renders, but that reference is not counted or protected here. Deleting a storage service instance that a render template depends on succeeds, with or without force, and leaves the render template pointing at a storage service instance that no longer exists.

ParameterTypeDefaultDescription
forcestringfalseAccepts exactly true or false. Any other value is rejected with a 400 naming the parameter, rather than being read as false