Create, update and delete services through the API
Create a service, save a complete definition, delete an undeployed service or prepare a deployment request through the Builder REST API. For discovery, fields and current definitions, start with List services, metadata and form schemas.
Host and authentication
Use https://govforms.uk (or your private Builder host) with the prefix below. Send your library API key in the Authorization header and JSON request bodies with Content-Type: application/json.
/builder/libraries/{libraryId}/api
Authorization: GovformsApiKey <key-id>:<key-secret>
GovformsApiHmac authentication and configured source-IP restrictions also apply. Use the Service ID for formId; the ordinary create, read, save and delete routes also accept its library-prefixed form.
Endpoints and permissions
Paths in this table follow the Builder prefix above.
| Method and path | Permission | Behaviour |
|---|---|---|
POST /forms/{formId} |
apiFormWrite | Create a new service; an existing ID returns 409. |
DELETE /forms/{formId} |
apiFormWrite | Delete a service after it has been undeployed. |
POST /darcy/form-lock/{formId} |
apiFormWrite | Acquire a lock and read the latest definition. |
PUT /darcy/form-lock/{formId} |
apiFormWrite | Renew the lock. |
DELETE /darcy/form-lock/{formId} |
apiFormWrite | Release the lock. |
PUT /save-form-version/{formId} |
apiFormWrite | Replace the full definition of an existing service under the lock. |
POST /deployments |
apiFormDeploy | Prepare a service deployment or withdrawal request. |
PUT /upsert-service-definition/{formId} |
upsertServiceDefinition | Create or replace a complete definition using the existing upsert contract. |
PUT /start-deployment/{formId}/{version}/{env} |
triggerServiceDeployment | Prepare a deployment request for an explicit environment. |
Creating from a supplied full definition and saving/upserting a definition use 25 API units. Creating from a name, deleting and preparing deployment requests use 5 units. The lock calls use 1 unit. Limits and error headers follow the API overview.
Create a service
POST /builder/libraries/demolibrary/api/forms/example-application
{"formName": "Example application"}
Omit form to start with the standard empty service, or supply a full Govform definition in the form property. The optional _ssType property describes the creation in change history. Identity fields are derived from the path. The API validates the definition and its referenced integrations; custom-domain provisioning is managed through Builder.
Success returns 201 with an object containing success: true and form: a service summary. A saved Builder design is not automatically deployed.
Save an existing definition with a lock
- POST /darcy/form-lock/{formId}, without a request body. The response contains lockId and the latest full form object.
- Modify that returned form, retaining configuration your edit does not change. This is a full-definition replacement, not a partial patch.
- PUT /save-form-version/{formId}, sending the full form object as the body and the returned lockId in the X-Form-Lock-Id header. Set _ssType to a useful change description. Optional X-On-Behalf-Of identifies the person or integration in change history.
- Release the lock with DELETE /darcy/form-lock/{formId}, sending {"lockId": "returned-lock-id"} as JSON, including after a failed save.
Locks expire after 30 seconds unless renewed. PUT /darcy/form-lock/{formId} with the same JSON lockId renews the lock and returns success: true. A missing, expired or conflicting save lock returns 409; missing or non-string renewal/release IDs return 400. Reacquire and read the latest definition after a conflict before reconstructing the edit.
A successful save returns success, formIdWithOrg, versionNum and _ssId. Preserve the returned revision as application metadata; identity and version values are assigned by Govform. Saving does not deploy the service.
Delete an undeployed service
DELETE /forms/{formId} has no request body and returns {"success": true}. A deployed service must be undeployed first. Managed Collection forms use Collection programme operations; embedded-service references and shared-domain dependencies can also prevent deletion. A missing form returns 404 and a conflicting dependency or deployment returns 409.
Prepare a deployment request
POST /builder/libraries/demolibrary/api/deployments
{"formId": "example-application", "version": "latest", "environment": "qa", "undeploy": false}
environment is qa, production or staging where enabled. version can be latest (also the default) or a saved version number. Set undeploy: true for a withdrawal.
The response contains success, deploymentId, formIdWithOrg, environment and isUndeploy. It identifies a prepared, short-lived request; it does not confirm that the service has been deployed. For an integration that triggers deployment through the service environment, use Trigger service deployment and check the current deployed version afterwards. Managed Collection forms must be applied through their Collection programme.
Existing upsert and explicit-environment contracts
PUT /upsert-service-definition/{formId} requires the library-prefixed formId and a complete form object as its JSON body. It creates a missing service or saves a new version of an existing one. Supply formName and a non-empty pages array; pages require IDs, titles and fields arrays. Field types must be valid. If supplied, id must match the Service ID and idWithOrg must match the prefixed path ID. isAnonymous uses the strings "true" or "false". This route returns HTTP 200 on success, rather than a service summary. Its legacy validation errors can use a top-level message, and some errors have no JSON body.
PUT /start-deployment/{formId}/{version}/{env} takes the unprefixed Service ID, no request body, and an explicit qa, production or enabled staging environment. version is latest, remove or a numeric version previously deployed to an environment. It returns {"deploymentId": "..."} for the prepared request. This is not a current-status response and does not by itself deliver the definition to the target environment.
These routes have separate permissions from apiFormWrite and apiFormDeploy. Existing integrations should retain their own identifier and response contracts.
Errors and release checks
Ordinary Builder routes return JSON error.message for validation, authentication, missing records and conflicts: 400, 403, 404 or 409. Capacity limits return 429. Production deployment requests also depend on the library's deployment eligibility. After any deployment operation, check the target environment rather than interpreting a prepared request ID as completion.
See authentication headers for raw-key and HMAC formats.
