API Design

API design is a large topic. We expect this page to grow over time.

OpenAPI

As you add API endpoints, please be conscious that we are exposing these endpoints as an OpenAPI document at /openapi (e.g. http://localhost:8080/openapi ). See Getting the OpenAPI Document in the API Guide for the user-facing documentation.

OpenAPI Annotations

To keep our OpenAPI document at a reasonable quality, you must add annotations to API endpoints you are adding and editing. Here’s an example:

@POST
@AuthRequired
@Path("/")
@Operation(summary = "Creates a license", description = "Creates a license when the authenticated user is a superuser and returns the created license location.")
@APIResponse(responseCode = "201", description = "License created with a Location header pointing to the new license.")
public Response addLicense(@Context ContainerRequestContext crc,
        @RequestBody(description = "License definition to persist, including name, URI, active state, and sort order.",
                content = @Content(mediaType = "application/json",
                        schema = @Schema(type = SchemaType.OBJECT,
                                description = "License definition accepted by the license administration API.")))
        License license) {
...
}

If you are looking for a reference about the annotations used to generate the OpenAPI document, you can find it in the MicroProfile OpenAPI Specification.

OpenAPI Quality

To use vacuum with our recommended settings to check the quality of our OpenAPI document, see the README.md under scripts/openapi.

You can prevent additional problems in our OpenAPI document by observing the following practices:

  • When creating a method name within an API class, make it unique.

  • Check that HTTP GET and DELETE operations do not accept request bodies.

  • Various notes under vacuum-recommended.yaml.

Paths

A reminder from Wikipedia of what a path is:

        userinfo       host      port
        ┌──┴───┐ ┌──────┴──────┐ ┌┴┐
https://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top
└─┬─┘   └─────────────┬────────────┘└───────┬───────┘ └────────────┬────────────┘ └┬┘
scheme          authority                  path                  query           fragment

Exposing Settings

Since Dataverse 4, database settings have been exposed via API at http://localhost:8080/api/admin/settings

(JVM options are probably available via the Payara REST API, but this is out of scope.)

Settings need to be exposed outside to API clients outside of /api/admin (which is typically restricted to localhost). Here are some guidelines to follow when exposing settings.

  • When you are exposing a database setting as-is:

    • Use /api/info/settings as the root path.

    • Append the name of the setting including the colon (e.g. :DatasetPublishPopupCustomText)

    • Final path example: /api/info/settings/:DatasetPublishPopupCustomText

  • If the absence of the database setting is filled in by a default value (e.g. :ZipDownloadLimit or :ApiTermsOfUse):

    • Use /api/info as the root path.

    • Append the setting but remove the colon and downcase the first character (e.g. zipDownloadLimit)

    • Final path example: /api/info/zipDownloadLimit

  • If the database setting you’re exposing make more sense outside of /api/info because there’s more context (e.g. :CustomDatasetSummaryFields):

    • Feel free to use a path outside of /api/info as the root path.

    • Given additional context, append a shortened name (e.g. /api/datasets/summaryFieldNames).

    • Final path example: /api/datasets/summaryFieldNames

  • If you need to expose a JVM option (MicroProfile setting) such as dataverse.api.allow-incomplete-metadata:

    • Use /api/info as the root path.

    • Append a meaningful name for the setting (e.g. incompleteMetadataViaApi).

    • Final path example: /api/info/incompleteMetadataViaApi