| openapi: 3.0.1 |
| info: |
| title: Eclipse Hono™ Device Registry API |
| description: | |
| This API defines how to manage *Tenants*, *Devices*, and *Credentials*. |
| It acts as a common basis which all Hono device registries should |
| implement. |
| |
| ## Required APIs |
| |
| All operations, except the `tenants` resource are required. The tenant |
| management might be outside of the scope of the device registry and |
| managed by a higher level system. In this case all calls should simply |
| return `404`. However, if the `tenants` resource is implemented, then all |
| operations of it must be implemented. |
| |
| ## Security |
| |
| This specification explicitly leaves out the part of authenticating and |
| authorizing users with the device registry. It is assumed that some form |
| of token exchange between the user agent and the backend service will |
| take place. Like for example HTTP basic authentication, or a bearer token. |
| |
| ## Code generation |
| |
| This model is not optimized for generating code from it. Code generators |
| try to understand the model and then translate this into the require |
| programming language. Even if the there would be no bugs in the code |
| generators, that process would be already only be an approximation. So |
| this model does focus in the description of the API, and doesn't tweak |
| the specification in a way to please code generators. |
| |
| contact: |
| name: Contact details |
| url: https://www.eclipse.org/hono/community/get-in-touch/ |
| license: |
| name: EPL-2.0 |
| url: https://www.eclipse.org/legal/epl-2.0/ |
| version: 1.0.0 |
| |
| externalDocs: |
| description: Eclipse Hono™ web page |
| url: https://eclipse.org/hono |
| |
| tags: |
| - name: tenants |
| description: Tenant Management (optional) |
| externalDocs: |
| description: Hono Multi-Tenancy |
| url: https://www.eclipse.org/hono/docs/concepts/tenancy/ |
| - name: devices |
| description: Device registration |
| externalDocs: |
| description: Hono device identity |
| url: https://www.eclipse.org/hono/docs/concepts/device-identity/ |
| - name: credentials |
| description: Device credentials |
| |
| externalDocs: |
| description: Hono device identity |
| url: https://www.eclipse.org/hono/docs/concepts/device-identity/ |
| |
| servers: |
| - url: '{corsProxy}{server}/v1' |
| variables: |
| server: |
| default: http://hono.eclipse.org:28080 |
| corsProxy: |
| default: https://cors-anywhere.herokuapp.com/ |
| |
| security: |
| - BearerAuth: [] |
| - BasicAuth: [] |
| |
| paths: |
| |
| # Tenant API |
| |
| /tenants: |
| |
| post: |
| tags: |
| - tenants |
| summary: Create new tenant with auto-generated ID |
| operationId: createTenant |
| requestBody: |
| description: New tenant information |
| content: |
| application/json: |
| schema: |
| $ref: '#/components/schemas/Tenant' |
| required: true |
| responses: |
| 201: |
| $ref: '#/components/responses/Created' |
| 400: |
| $ref: '#/components/responses/MalformedRequest' |
| 401: |
| $ref: '#/components/responses/Unauthorized' |
| 403: |
| $ref: '#/components/responses/NotAllowed' |
| |
| /tenants/{tenantId}: |
| |
| parameters: |
| - $ref: '#/components/parameters/tenantId' |
| |
| post: |
| tags: |
| - tenants |
| summary: Create new tenant |
| operationId: createTenantWithId |
| requestBody: |
| description: New tenant registration |
| content: |
| application/json: |
| schema: |
| $ref: '#/components/schemas/Tenant' |
| required: true |
| responses: |
| 201: |
| $ref: '#/components/responses/Created' |
| 400: |
| $ref: '#/components/responses/MalformedRequest' |
| 401: |
| $ref: '#/components/responses/Unauthorized' |
| 403: |
| $ref: '#/components/responses/NotAllowed' |
| 409: |
| $ref: '#/components/responses/AlreadyExists' |
| |
| get: |
| tags: |
| - tenants |
| summary: Get tenant information |
| operationId: getTenant |
| responses: |
| 200: |
| description: operation successful |
| content: |
| application/json: |
| schema: |
| $ref: '#/components/schemas/Tenant' |
| headers: |
| ETag: |
| description: Version of the resource |
| schema: |
| type: string |
| 400: |
| $ref: '#/components/responses/MalformedRequest' |
| 401: |
| $ref: '#/components/responses/Unauthorized' |
| 404: |
| $ref: '#/components/responses/NotFound' |
| |
| put: |
| tags: |
| - tenants |
| summary: Update tenant information |
| operationId: updateTenant |
| parameters: |
| - $ref: '#/components/parameters/resourceVersion' |
| requestBody: |
| description: Tenant information |
| content: |
| application/json: |
| schema: |
| $ref: '#/components/schemas/Tenant' |
| required: true |
| responses: |
| 204: |
| $ref: '#/components/responses/Updated' |
| 400: |
| $ref: '#/components/responses/MalformedRequest' |
| 401: |
| $ref: '#/components/responses/Unauthorized' |
| 403: |
| $ref: '#/components/responses/NotAllowed' |
| 404: |
| $ref: '#/components/responses/NotFound' |
| 412: |
| $ref: '#/components/responses/ResourceVersionMismatch' |
| |
| delete: |
| tags: |
| - tenants |
| summary: Delete tenant |
| operationId: deleteTenant |
| parameters: |
| - $ref: '#/components/parameters/resourceVersion' |
| responses: |
| 204: |
| $ref: '#/components/responses/Deleted' |
| 401: |
| $ref: '#/components/responses/Unauthorized' |
| 403: |
| $ref: '#/components/responses/NotAllowed' |
| 404: |
| $ref: '#/components/responses/NotFound' |
| 412: |
| $ref: '#/components/responses/ResourceVersionMismatch' |
| |
| # Device API |
| |
| /devices/{tenantId}: |
| |
| parameters: |
| - $ref: '#/components/parameters/tenantId' |
| |
| post: |
| tags: |
| - devices |
| summary: Create new device registration with auto-generated ID |
| operationId: createDeviceRegistration |
| requestBody: |
| description: New device |
| content: |
| application/json: |
| schema: |
| $ref: '#/components/schemas/Device' |
| required: true |
| responses: |
| 201: |
| $ref: '#/components/responses/Created' |
| 400: |
| $ref: '#/components/responses/MalformedRequest' |
| 401: |
| $ref: '#/components/responses/Unauthorized' |
| 403: |
| $ref: '#/components/responses/NotAllowed' |
| |
| /devices/{tenantId}/{deviceId}: |
| |
| parameters: |
| - $ref: '#/components/parameters/tenantId' |
| - $ref: '#/components/parameters/deviceId' |
| |
| post: |
| tags: |
| - devices |
| summary: Create new device registration |
| operationId: createDeviceRegistrationWithId |
| requestBody: |
| description: New device |
| content: |
| application/json: |
| schema: |
| $ref: '#/components/schemas/Device' |
| required: true |
| responses: |
| 201: |
| $ref: '#/components/responses/Created' |
| 400: |
| $ref: '#/components/responses/MalformedRequest' |
| 401: |
| $ref: '#/components/responses/Unauthorized' |
| 403: |
| $ref: '#/components/responses/NotAllowed' |
| 409: |
| $ref: '#/components/responses/AlreadyExists' |
| |
| get: |
| tags: |
| - devices |
| summary: Get device registration information |
| operationId: getRegistration |
| responses: |
| 200: |
| description: operation successful |
| content: |
| application/json: |
| schema: |
| $ref: '#/components/schemas/Device' |
| headers: |
| ETag: |
| description: Version of the resource |
| schema: |
| type: string |
| 400: |
| $ref: '#/components/responses/MalformedRequest' |
| 401: |
| $ref: '#/components/responses/Unauthorized' |
| 404: |
| $ref: '#/components/responses/NotFound' |
| |
| put: |
| tags: |
| - devices |
| summary: Update existing device registration |
| operationId: updateRegistration |
| parameters: |
| - $ref: '#/components/parameters/resourceVersion' |
| requestBody: |
| description: Updated device registration |
| content: |
| application/json: |
| schema: |
| $ref: '#/components/schemas/Device' |
| required: true |
| responses: |
| 204: |
| $ref: '#/components/responses/Updated' |
| 400: |
| $ref: '#/components/responses/MalformedRequest' |
| 401: |
| $ref: '#/components/responses/Unauthorized' |
| 403: |
| $ref: '#/components/responses/NotAllowed' |
| 404: |
| $ref: '#/components/responses/NotFound' |
| 412: |
| $ref: '#/components/responses/ResourceVersionMismatch' |
| |
| delete: |
| tags: |
| - devices |
| summary: Delete device registration |
| operationId: deleteRegistration |
| parameters: |
| - $ref: '#/components/parameters/resourceVersion' |
| responses: |
| 204: |
| $ref: '#/components/responses/Deleted' |
| 401: |
| $ref: '#/components/responses/Unauthorized' |
| 403: |
| $ref: '#/components/responses/NotAllowed' |
| 404: |
| $ref: '#/components/responses/NotFound' |
| 412: |
| $ref: '#/components/responses/ResourceVersionMismatch' |
| |
| /credentials/{tenantId}/{deviceId}: |
| |
| parameters: |
| - $ref: '#/components/parameters/tenantId' |
| - $ref: '#/components/parameters/deviceId' |
| |
| get: |
| tags: |
| - credentials |
| summary: Get credentials set of a device. |
| description: | |
| Get the credentials set of a device. As long as the device is |
| registered and the user has read access to it, this call should |
| never return "not found". |
| Depending on its implementation (or configuration), the device registry |
| can either return all credentials information including full secret details or |
| secret metadata along with the generated identifier (an `id` property). |
| The identifier can be used for the follow-up `update` operation). |
| operationId: getAllCredentials |
| responses: |
| 200: |
| description: Operation successful |
| content: |
| application/json: |
| schema: |
| $ref: '#/components/schemas/CredentialsSet' |
| examples: |
| Full Credentials: |
| $ref: '#/components/examples/HashedPasswordExample' |
| Credentials Metadata: |
| $ref: '#/components/examples/MetaPasswordExample' |
| headers: |
| ETag: |
| description: Version of the resource |
| schema: |
| type: string |
| 400: |
| $ref: '#/components/responses/MalformedRequest' |
| 401: |
| $ref: '#/components/responses/Unauthorized' |
| 404: |
| $ref: '#/components/responses/NotFound' |
| |
| put: |
| tags: |
| - credentials |
| summary: Update credentials set for registered device |
| description: If the device registry is handling full secret details, the updated credential set |
| will be an exact match of the provided content. If it is using secret metadata, |
| data will be merged in based on the secret identities. |
| operationId: setAllCredentials |
| parameters: |
| - $ref: '#/components/parameters/resourceVersion' |
| requestBody: |
| content: |
| application/json: |
| schema: |
| $ref: '#/components/schemas/CredentialsSet' |
| examples: |
| Hashed Password: |
| $ref: '#/components/examples/HashedPasswordExample' |
| Plain Password: |
| $ref: '#/components/examples/PlainPasswordExample' |
| required: true |
| responses: |
| 204: |
| $ref: '#/components/responses/Updated' |
| 400: |
| $ref: '#/components/responses/MalformedRequest' |
| 401: |
| $ref: '#/components/responses/Unauthorized' |
| 403: |
| $ref: '#/components/responses/NotAllowed' |
| 404: |
| $ref: '#/components/responses/NotFound' |
| 412: |
| $ref: '#/components/responses/ResourceVersionMismatch' |
| |
| components: |
| |
| schemas: |
| |
| # Common schema |
| |
| Error: |
| type: object |
| additionalProperties: true |
| required: |
| - error |
| properties: |
| "error": |
| type: string |
| description: A human readable error message of what went wrong. |
| |
| DefaultProperties: |
| type: object |
| additionalProperties: true |
| description: Defaults for properties defined on the tenant and device level. |
| |
| Extensions: |
| type: object |
| additionalProperties: true |
| description: Allows arbitrary properties as extension to the ones |
| specified by the Hono API. |
| |
| # Tenant schema |
| |
| Tenant: |
| type: object |
| additionalProperties: false |
| properties: |
| "enabled": |
| type: boolean |
| default: true |
| "ext": |
| $ref: '#/components/schemas/Extensions' |
| "adapters": |
| type: array |
| description: Only a single entry per type is allowed. If multiple entries for the same type are present it is handled as an error. |
| items: |
| $ref: '#/components/schemas/Adapter' |
| "defaults": |
| $ref: '#/components/schemas/DefaultProperties' |
| "minimum-message-size": |
| type: integer |
| default: 0 |
| description: The minimum message size in bytes. If it is set |
| then the payload size of the telemetry, event and |
| command messages are calculated in accordance with |
| the configured value and then reported to the metrics. |
| "limits": |
| $ref: '#/components/schemas/ResourceLimit' |
| "trusted-ca": |
| $ref: '#/components/schemas/TrustedCA' |
| |
| TrustedCA: |
| type: object |
| additionalProperties: false |
| required: |
| - "subject-dn" |
| properties: |
| "subject-dn": |
| type: string |
| description: The subject DN of the trusted root certificate in |
| the format defined by RFC 2253. |
| "public-key": |
| type: string |
| format: byte |
| description: The Base64 encoded binary DER encoding of the |
| trusted root certificate’s public key. |
| Either this property or `cert` must be set. |
| "cert": |
| type: string |
| format: byte |
| description: The Base64 encoded binary DER encoding of the |
| trusted root certificate. Either this property |
| or `public-key` must be set. |
| "algorithm": |
| type: string |
| description: The algorithm used for the public key of the CA. |
| If the `cert` property is used to provide an |
| X.509 certificate then the algorithm is determined |
| from the certificate and this property is ignored. |
| Otherwise, i.e. if the `public-key` property is |
| used, this property must be set to the algorithm |
| used, if other than the default. |
| default: RSA |
| example: EC |
| |
| Adapter: |
| type: object |
| additionalProperties: true |
| required: |
| - type |
| properties: |
| "type": |
| type: string |
| "enabled": |
| type: boolean |
| default: false |
| "device-authentication-required": |
| type: boolean |
| default: true |
| "ext": |
| $ref: '#/components/schemas/Extensions' |
| |
| ResourceLimit: |
| type: object |
| additionalProperties: false |
| properties: |
| "max-connections": |
| type: integer |
| default: -1 |
| description: The maximum number of concurrent connections allowed |
| from devices of this tenant. The default value -1 |
| indicates that no limit is set. |
| "ext": |
| $ref: '#/components/schemas/Extensions' |
| |
| # Devices schema |
| |
| Device: |
| type: object |
| additionalProperties: false |
| properties: |
| "enabled": |
| type: boolean |
| default: true |
| "defaults": |
| $ref: '#/components/schemas/DefaultProperties' |
| "via": |
| type: array |
| items: |
| type: string |
| description: The device IDs of the gateways this device is assigned to. |
| "ext": |
| $ref: '#/components/schemas/Extensions' |
| |
| # Credentials |
| |
| CredentialsSet: |
| type: array |
| description: A set of credentials. The entries in this list must be |
| unique by the composite key of `auth-id` and `type`. |
| items: |
| $ref: '#/components/schemas/TypedCredentials' |
| |
| TypedCredentials: |
| additionalProperties: false |
| oneOf: |
| - $ref: '#/components/schemas/PasswordCredentials' |
| - $ref: '#/components/schemas/PSKCredentials' |
| - $ref: '#/components/schemas/X509CertificateCredentials' |
| discriminator: |
| propertyName: type |
| mapping: |
| "hashed-password": '#/components/schemas/PasswordCredentials' |
| "psk": '#/components/schemas/PSKCredentials' |
| "x509-cert": '#/components/schemas/X509CertificateCredentials' |
| |
| CommonCredentials: |
| type: object |
| additionalProperties: false |
| required: |
| - auth-id |
| - type |
| properties: |
| "type": |
| type: string |
| "auth-id": |
| type: string |
| "enabled": |
| type: boolean |
| default: true |
| "ext": |
| $ref: '#/components/schemas/Extensions' |
| |
| PasswordCredentials: |
| additionalProperties: false |
| allOf: |
| - $ref: '#/components/schemas/CommonCredentials' |
| - type: object |
| additionalProperties: false |
| properties: |
| "secrets": |
| type: array |
| items: |
| $ref: '#/components/schemas/PasswordSecret' |
| |
| PSKCredentials: |
| additionalProperties: false |
| allOf: |
| - $ref: '#/components/schemas/CommonCredentials' |
| - type: object |
| additionalProperties: false |
| properties: |
| "secrets": |
| type: array |
| items: |
| $ref: '#/components/schemas/PSKSecret' |
| |
| X509CertificateCredentials: |
| additionalProperties: false |
| allOf: |
| - $ref: '#/components/schemas/CommonCredentials' |
| - type: object |
| additionalProperties: false |
| properties: |
| "secrets": |
| type: array |
| items: |
| $ref: '#/components/schemas/X509CertificateSecret' |
| |
| CommonSecret: |
| type: object |
| additionalProperties: false |
| properties: |
| "id": |
| type: string |
| description: The device registry can assign an identity to the secret. |
| This value can be used to update secrets based on their metadata. |
| "enabled": |
| type: boolean |
| default: true |
| "not-before": |
| type: string |
| format: date-time |
| "not-after": |
| type: string |
| format: date-time |
| "comment": |
| type: string |
| |
| X509CertificateSecret: |
| additionalProperties: false |
| allOf: |
| - $ref: '#/components/schemas/CommonSecret' |
| |
| PasswordSecret: |
| additionalProperties: false |
| allOf: |
| - $ref: '#/components/schemas/CommonSecret' |
| - type: object |
| additionalProperties: false |
| properties: |
| "hash-function": |
| type: string |
| example: sha-512 |
| description: The name of the hash function used to create the password hash (defined in `pwd-hash` property). |
| If the password is defined using a `pwd-plain` property, this value will be ignored by the device registry. |
| This property should be empty when returning passwords from the device registry using only secret metadata. |
| In this case the id field must be set instead. |
| "pwd-hash": |
| type: string |
| format: byte |
| description: The password hash created using the `hash-function` and optional `salt` values. |
| If the password is defined using a `pwd-plain` property, this value will be ignored by the device registry. |
| This property should be empty when returning passwords from the device registry using only secret metadata. |
| In this case the id field must be set instead. |
| "salt": |
| type: string |
| format: byte |
| description: The Base64 encoding of the salt used in the password hash (defined in the `pwd-hash` property). |
| If the password is defined using a `pwd-plain` property, this value will be ignored by the device registry. |
| This property should be empty when returning passwords from the device registry using only secret metadata. |
| In this case the id field must be set instead. |
| "pwd-plain": |
| type: string |
| format: byte |
| description: The clear text value of the password to be hashed by the device registry. |
| If this property is specified, the device registry will ignore user-provided hash properties (`hash-function`, `pwd-hash` and `salt`). |
| This property should never be stored by the device registry. |
| This property should be empty when returning passwords from the device registry. |
| |
| PSKSecret: |
| additionalProperties: false |
| allOf: |
| - $ref: '#/components/schemas/CommonSecret' |
| - type: object |
| additionalProperties: false |
| required: |
| - key |
| properties: |
| "key": |
| type: string |
| format: byte |
| |
| parameters: |
| |
| resourceVersion: |
| name: If-Match |
| in: header |
| description: The expected resource version |
| required: false |
| schema: |
| type: string |
| |
| tenantId: |
| name: tenantId |
| in: path |
| description: The ID of the tenant |
| required: true |
| schema: |
| type: string |
| example: DEFAULT_TENANT |
| |
| deviceId: |
| name: deviceId |
| in: path |
| description: The ID of the device |
| required: true |
| schema: |
| type: string |
| example: 4711 |
| |
| authId: |
| name: authId |
| in: path |
| description: The authentication ID of the device |
| required: true |
| schema: |
| type: string |
| example: sensor1 |
| |
| type: |
| name: type |
| in: path |
| description: The credentials type |
| required: true |
| schema: |
| type: string |
| example: sha-256 |
| |
| responses: |
| |
| Unauthorized: |
| description: Authentication credentials are required, but missing. |
| headers: |
| "WWW-Authenticate": |
| schema: |
| type: string |
| |
| Created: |
| description: Object created. |
| headers: |
| Location: |
| description: URL to the resource |
| schema: |
| type: string |
| format: uri |
| ETag: |
| description: The new version of the resource |
| schema: |
| type: string |
| content: |
| application/json: |
| schema: |
| type: object |
| additionalProperties: false |
| required: |
| - id |
| properties: |
| id: |
| type: string |
| description: The ID of the created object |
| |
| Updated: |
| description: Object updated. |
| headers: |
| ETag: |
| description: The new version of the resource |
| schema: |
| type: string |
| |
| Deleted: |
| description: Object deleted. |
| |
| NotFound: |
| description: | |
| Object not found. This may also be returned for some operations |
| if the user misses read access for the object. |
| content: |
| application/json: |
| schema: |
| $ref: '#/components/schemas/Error' |
| |
| NotAllowed: |
| description: | |
| Operation not allowed. If the user does not have read access |
| for this object, then `404` will be returned instead. |
| content: |
| application/json: |
| schema: |
| $ref: '#/components/schemas/Error' |
| |
| MalformedRequest: |
| description: Malformed request |
| content: |
| application/json: |
| schema: |
| $ref: '#/components/schemas/Error' |
| |
| AlreadyExists: |
| description: | |
| Object already exists. If the user has no read access for |
| the existing object, then `403` should be returned instead. |
| content: |
| application/json: |
| schema: |
| $ref: '#/components/schemas/Error' |
| |
| ResourceVersionMismatch: |
| description: | |
| Expected resource version does not match current. |
| This can only happen when the request header `If-Match` |
| was set. |
| content: |
| application/json: |
| schema: |
| $ref: '#/components/schemas/Error' |
| |
| securitySchemes: |
| |
| BearerAuth: |
| type: http |
| scheme: bearer |
| |
| BasicAuth: |
| type: http |
| scheme: basic |
| |
| examples: |
| HashedPasswordExample: |
| value: |
| auth-id: sensor1 |
| type: hashed-password |
| secrets: [{ |
| "not-after": "2027-12-24T19:00:00Z", |
| "pwd-hash": "AQIDBAUGBwg=", |
| "salt": "Mq7wFw==", |
| "hash-function": "sha-512" |
| }] |
| PlainPasswordExample: |
| value: |
| auth-id: sensor1 |
| type: hashed-password |
| secrets: [{ |
| "id": "349556ea-4902-47c7-beb0-1009ab693fb4", |
| "not-after": "2027-12-24T19:00:00Z", |
| "pwd-plain": "hono-secret" |
| }] |
| MetaPasswordExample: |
| value: |
| auth-id: sensor1 |
| type: hashed-password |
| secrets: [{ |
| "id": "349556ea-4902-47c7-beb0-1009ab693fb4", |
| "not-after": "2027-12-24T19:00:00Z", |
| "pwd-plain": "", |
| "pwd-hash": "", |
| "salt": "", |
| "hash-function": "" |
| }] |