Skip to content

Custom APIs

Peter McDonald edited this page Aug 12, 2026 · 2 revisions

Custom APIs

Define a Custom API as a file in your repo, generate the C# handler and a typed TypeScript client from it, and deploy it to your environment — so the API's shape lives in source control next to the plug-in that implements it, rather than only in the environment you last clicked it into.

Preview feature. Tick Preview features in the panel footer to see these commands.

Where it lives

A Custom API is a *.customapi.json file directly inside a Plugins component, because a Custom API is implemented by a plug-in type. One file per API. The commands are on the plugin card's overflow () menu:

Command What it does
New Custom API definition Scaffolds <UniqueName>.customapi.json with a sample request parameter and response property
Generate Custom API handlers Writes/refreshes the C# handler class for each definition
Generate Custom API TS clients Writes a typed TypeScript client for each definition
Deploy Custom APIs Creates or updates the API, its request parameters and its response properties in the environment
Run Custom API… Calls a deployed API and shows the response

1. Define it

New Custom API definition asks for two things:

  1. the unique name (e.g. dvpt_CalculateRebate) — the name callers use;
  2. the plug-in type name, defaulted from that unique name (e.g. Dataverse.Plugins.CalculateRebate) — the class that will implement it.

The result is a JSON file describing the API: its binding, whether it is a function or an action, its request parameters and its response properties. Edit that file as the source of truth — everything below is generated from it, and validation errors are reported per file with the offending field named, so a typo is caught before it reaches the environment.

2. Generate the handler and the client

Generate Custom API handlers writes the C# side into your plug-in project, at <PluginProject>/CustomApi/<Class>.generated.cs: typed request and response wrappers plus an IPlugin class with a TODO. Fill that in — read the inputs from request, set the outputs on response:

response.OutputValue = "echo: " + request.InputValue;

Generate Custom API TS clients writes the TypeScript side to clients/<Class>.client.ts — a typed function a web resource or PCF control can call. Copy it into that project.

Re-run either after editing the definition.

Regenerating overwrites the whole file, including the logic you wrote in Execute. Until that changes (#254), either keep your implementation somewhere else and call it from Execute — a one-line call is safe to retype — or copy the file before regenerating.

3. Deploy it

Deploy Custom APIs validates every definition in the component, then for each one:

  1. creates the Custom API if it is absent, or updates it if it exists (matched on unique name);
  2. reconciles the request parameters and response properties — creating what is new, updating what changed, and deleting what you removed from the definition, so the environment ends up matching the file rather than accumulating members from earlier versions;
  3. adds it to your solution.

Deploy the implementing plug-in as well (Build & deploy package on the same card) — the Custom API row points at a plug-in type, so the type has to exist.

4. Call it

Run Custom API… picks a definition, prompts for each request parameter, calls the API and shows what came back.

Global (unbound) APIs only. A Custom API bound to a table or an entity collection cannot be invoked from here yet — the command says so and points you at the generated TypeScript client, which handles bound calls.

Status

The full loop — define, generate, deploy the package, deploy the API, call it — runs against a live environment in the automated end-to-end suite, which checks the customapi row and its members in Dataverse and asserts the response the handler returns. Sign-off for un-gating the feature is tracked in #225.

Troubleshooting

The commands are not in the menu — tick Preview features in the panel footer, and make sure the active component is a Plugins component.

"✗ <name>: N validation error(s)" — the definition failed validation and was skipped; each error names its field. Nothing is deployed for that file until it is clean.

"Running bound Custom APIs isn't supported yet" — expected, see above; use the generated TS client.

See also

  • Plugins — the component a Custom API lives in, and how to deploy its implementation
  • Solutions — how the API travels between environments

Clone this wiki locally