---
title: Specification of the plugin API
description: The first step in adding API support to your plugin is to implement the AuthnApiPlugin interface.
component: pingfederate
version: 13.1
page_id: pingfederate:sdk_developers_guide:pf_specification_plugin_api
canonical_url: https://docs.pingidentity.com/pingfederate/13.1/sdk_developers_guide/pf_specification_plugin_api.html
llms_txt: https://docs.pingidentity.com/pingfederate/llms.txt
docs_for_agents: https://developer.pingidentity.com/build-with-ai/docs-for-agents.md
revdate: July 5, 2022
section_ids:
  related-links: Related links
  state-model-example: State model example
  action-model-example: Action model example
  authnstatespec-and-authnactionspec-objects: AuthnStateSpec and AuthnActionSpec objects
  error-specifications: Error specifications
---

# Specification of the plugin API

The first step in adding API support to your plugin is to implement the `AuthnApiPlugin` interface.

The AuthnApiPlugin interface has two methods: `getApiSpec()` and `getApiPluginDescriptor()`. You only need to implement the `getApiSpec()` method. The API specification this method returns defines the states, models, and actions that your plugin exposes in the API.

The API specification is defined by the `*Spec` classes in the SDK. These include `AuthnStateSpec`, `AuthnActionSpec`, `AuthnErrorSpec`, and `AuthnErrorDetailSpec`. The information in these classes lets the PingFederate authentication API Explorer provide documentation for API client developers. That documentation describes your plugin's API and lets developers experiment with it.

You can access the API Explorer at https\://*PingFederate\_host*:9031/pf-ws/authn/explorer. To enable the API Explorer, go to the **Authentication API Applications** window and select the **Enable API Explorer** checkbox. An easy way to use the API Explorer is to create an authentication API application in PingFederate and set the URL for the application to the API Explorer's URL.

|   |                                                                                                                                                     |
| - | --------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | When defining models for states and actions, use the @Schema annotation to describe each field in the model and show whether the field is required. |

The rest of this document primarily uses the `TemplateRenderAdapter` as an example. The source for this adapter is in the PingFederate installation package's `sdk/plugin-src/template-render-adapter-example` directory. This adapter is simple. It just prompts the user to enter their username and provide a set of string attributes. The administrator defines the list of attributes by extending the adapter contract. The attribute values are passed back in the `SubmitUserAttributes` model as a map. Representing field values using a map in the model is unusual. Usually a separate field in the model defines each allowed field, which provides better type safety in the code.

## Related links

* [Developing authentication API-capable adapters and selectors](pf_develop_auth_api_capable_adapt_selec.html)

## State model example

The following is an example of a state model used by the `TemplateRenderAdapter`.

```
/
 * This is the model for the USER_ATTRIBUTES_REQUIRED state. It defines the
 * fields that are returned to the API client in a GET response for this state.
 /
public class UserAttributesRequired
{
	private List<String> attributeNames = new ArrayList<>();

	/
	 * Get the list of user attributes supported by this adapter instance.
	 *
	 * It is recommended to annotate each getter with the @Schema annotation
	 * and provide a description. This description will be used in
	 * generating API documentation.
	 */
	@Schema(description="A list of user attribute names that are supported by this adapter instance.")
	public List<String> getAttributeNames()
	{
		return attributeNames;
	}

	/*
	 * Set the list of user attributes supported by this adapter instance.
	 */
	public void setAttributeNames(List<String> attributeNames)
	{
		this.attributeNames = attributeNames;
	}
}
```

## Action model example

The following is the model for the `submitUserAttributes` action.

```
/
 * This is the model for the submitUserAttributes API action. It defines the
 * fields that may be included in the POST body for this action.
 /
public class SubmitUserAttributes
{
	private String username;
	private Map<String,Object> userAttributes = new HashMap<>();

	/
	 * Get the username.
	 *
	 * It is recommended to annotate each getter with the @Schema annotation
	 * and provide a description. The 'required' flag can also be specified. This
	 * information will be used in generating API documentation.
	 */
	@Schema(description="The user's username.", required=true)
	public String getUsername()
	{
		return username;
	}

	/
	 * Set the username.
	 */
	public void setUsername(String username)
	{
		this.username = username;
	}

	/
	 * Get the user attributes.
	 */
	@Schema(description="Additional user attributes, as name-value pairs.")
	public Map<String, Object> getUserAttributes()
	{
		return userAttributes;
	}

	/*
	 * Set the user attributes.
	 */
	public void setUserAttributes(Map<String, Object> userAttributes)
	{
		this.userAttributes = userAttributes;
	}
}
```

## AuthnStateSpec and AuthnActionSpec objects

A fluent builder is provided for creating `AuthnStateSpec` and `AuthnActionSpec` objects.

Here is the definition of the `AuthnStateSpec` for the `USER_ATTRIBUTES_REQUIRED` state:

```
public final static AuthnStateSpec<UserAttributesRequired> USER_ATTRIBUTES_REQUIRED = new AuthnStateSpec.Builder<UserAttributesRequired>()
	.status("USER_ATTRIBUTES_REQUIRED")
	.description("The user's username and attributes are required.")
	.modelClass(UserAttributesRequired.class)
	.action(ActionSpec.SUBMIT_USER_ATTRIBUTES)
	.action(CommonActionSpec.CANCEL_AUTHENTICATION)
	.build();
```

Here is the specification for the `submitUserAttributes` action:

```
public final static AuthnActionSpec<SubmitUserAttributes> SUBMIT_USER_ATTRIBUTES = new AuthnActionSpec.Builder<SubmitUserAttributes>()
	.id("submitUserAttributes")
	.description("Submit the user's username and attributes.")
	.modelClass(SubmitUserAttributes.class)
	.error(CommonErrorSpec.VALIDATION_ERROR)
	.errorDetail(ErrorDetailSpec.INVALID_ATTRIBUTE_NAME)
	.build();
```

## Error specifications

Action specifications can include a list of possible errors and error details. Each top-level error that an authentication API request returns can include one or more error detail objects underneath it.

Typically, in the API specification, your only top-level error will be `CommonErrorSpec.VALIDATION_ERROR`. However, you can include error detail specifications that can appear under that top-level error.

The following is how the `TemplateRenderAdapter` defines the specification for the `INVALID_ATTRIBUTE_NAME` error detail.

```
public final static AuthnErrorDetailSpec INVALID_ATTRIBUTE_NAME = new AuthnErrorDetailSpec.Builder()
	.code("INVALID_ATTRIBUTE_NAME")
	.message("An invalid attribute name was provided.")
	.parentCode(CommonErrorSpec.VALIDATION_ERROR.getCode())
	.build();
```

|   |                                                                                                                                                                                           |
| - | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | The error detail specification must reference the error code of its parent top-level error. This ensures that the authentication API Explorer correctly represents the error information. |

`INVALID_ATTRIBUTE_NAME` is an example of an error that would be useful for API client developers but not for end users.

For more information about defining user-facing errors, see [\[pf\_error\_messages\_localization\]](#pf_error_messages_localization).
