Registry V3 Signing Keys
V3 signing key management endpoints
Lists signing keys for the current account/org/project with filtering and pagination. Results are ordered by creation time (newest first).
Unique identifier for the Harness account.
Unique identifier for the organization within the account.
Example: default or engineering_org
Unique identifier for the project within the organization.
Example: my_project or frontend_services
The page number for pagination (0-indexed).
Used to navigate through large result sets. Combined with size parameter
to control which subset of results to return.
Example: page=0 returns the first page, page=1 returns the second page
0The number of items to return per page.
Controls the page size for paginated results.
Example: size=50 returns up to 50 items per page
20Search term for filtering results.
Example: search_term=prod might match keys like "production", "prod-env", etc.
Filter signing keys by cryptographic system. Values match SigningKeyTypeV3, which is extensible. Example: types=GPG
GPGFilter signing keys by lifecycle state. Values match SigningKeyStatusV3, which is extensible. Example: statuses=ACTIVE
ACTIVEScope of signing keys to list
- none – current space only (default)
- ancestors – current space plus all parent spaces
If omitted, none is assumed. This field is extensible; clients must handle unknown values.
response for list signing keys
Pagination metadata.
pageselects which page of results to return (0 = first page).sizecontrols how many items are returned per page.hasMoreis true if more results exist after this page.
True if more results exist after this page.
trueThe current page (0-indexed)
0Number of items per page
20Error response.
GET /api/v3/signing-keys?account_identifier=text HTTP/1.1
Accept: */*
{
"hasMore": true,
"page": 0,
"size": 20,
"items": [
{
"algorithm": "RSA",
"createdAt": 1736360000123,
"createdBy": {
"display_name": "text",
"email": "text",
"type": "text",
"uid": "text"
},
"expirationAt": 1,
"fingerprint": "text",
"id": "123e4567-e89b-12d3-a456-426614174000",
"longKeyId": "text",
"modifiedAt": 1736360000123,
"name": "text",
"shortKeyId": "text",
"size": 1,
"source": "GENERATED",
"status": "ACTIVE",
"type": "GPG",
"updatedBy": {
"display_name": "text",
"email": "text",
"type": "text",
"uid": "text"
}
}
]
}Retrieves detailed information about a specific signing key by ID.
Unique identifier for the Harness account.
Signing key details
Error response.
GET /api/v3/signing-keys/{id}?account_identifier=text HTTP/1.1
Accept: */*
{
"data": {
"algorithm": "RSA",
"createdAt": 1736360000123,
"createdBy": {
"display_name": "text",
"email": "text",
"type": "text",
"uid": "text"
},
"expirationAt": 1,
"fingerprint": "text",
"id": "123e4567-e89b-12d3-a456-426614174000",
"longKeyId": "text",
"modifiedAt": 1736360000123,
"name": "text",
"shortKeyId": "text",
"size": 1,
"source": "GENERATED",
"status": "ACTIVE",
"type": "GPG",
"updatedBy": {
"display_name": "text",
"email": "text",
"type": "text",
"uid": "text"
}
}
}Soft-deletes a signing key by marking it as DELETED. The key metadata is retained for audit purposes. The key must not be attached to any registry: if it is, the request fails with 409 and the error message lists every registry to detach first.
Unique identifier for the Harness account.
Signing key deleted successfully
No content
Error response.
DELETE /api/v3/signing-keys/{id}?account_identifier=text HTTP/1.1
Accept: */*
No content
Updates a signing key's status.
Unique identifier for the Harness account.
Request to update a signing key status
New status for the key (cannot transition from REVOKED or DELETED). Intentionally a closed subset of SigningKeyStatusV3 rather than an extensible enum: DELETED is reachable only via DELETE /signing-keys/{id}, which emits a distinct audit event.
Signing key details
Error response.
PATCH /api/v3/signing-keys/{id}?account_identifier=text HTTP/1.1
Content-Type: application/json
Accept: */*
Content-Length: 19
{
"status": "ACTIVE"
}{
"data": {
"algorithm": "RSA",
"createdAt": 1736360000123,
"createdBy": {
"display_name": "text",
"email": "text",
"type": "text",
"uid": "text"
},
"expirationAt": 1,
"fingerprint": "text",
"id": "123e4567-e89b-12d3-a456-426614174000",
"longKeyId": "text",
"modifiedAt": 1736360000123,
"name": "text",
"shortKeyId": "text",
"size": 1,
"source": "GENERATED",
"status": "ACTIVE",
"type": "GPG",
"updatedBy": {
"display_name": "text",
"email": "text",
"type": "text",
"uid": "text"
}
}
}Returns the public key for a signing key in ASCII-armored format (PGP for GPG keys, PEM for RSA keys). Used by clients to verify signatures.
By default the key is returned inline as text/plain. Pass download=true to receive it as a file attachment instead, with a Content-Disposition header and a key-type-specific content type (application/pgp-keys with a .asc filename for GPG keys, application/x-pem-file with a .rsa.pub filename for RSA keys).
Unique identifier for the Harness account.
When true, the public key is returned as a file attachment with a Content-Disposition header and a key-type-specific content type (application/pgp-keys with a .asc filename for GPG keys, application/x-pem-file with a .rsa.pub filename for RSA keys). Defaults to false, which returns the ASCII-armored key inline as text/plain.
falsePublic key content. Returned inline as text/plain by default, or
as a file attachment when download=true.
Error response.
GET /api/v3/signing-keys/{id}/public-key?account_identifier=text HTTP/1.1
Accept: */*
binaryGenerates a new signing key (GPG or RSA), stores it in Harness Secret Manager, and persists metadata to the database. The private key is never stored in the database.
Unique identifier for the Harness account.
Unique identifier for the organization within the account.
Example: default or engineering_org
Unique identifier for the project within the organization.
Example: my_project or frontend_services
Request to generate a new signing key.
type selects the cryptographic system to generate:
- GPG: OpenPGP key for package signing (Debian, RPM, Alpine)
- RSA: Raw RSA key for direct signing operations
algorithm selects the underlying algorithm. Only RSA and ED25519 can
be generated; other SigningKeyAlgorithmV3 values (e.g. ECDSA) are
rejected with 400 here but may appear on imported keys.
Key size is not a request parameter. It is fixed per algorithm so that every generated key is one package clients are known to accept:
- GPG + ED25519: 256 bits (fixed by the curve)
- GPG + RSA: 4096 bits
- RSA + RSA: 4096 bits
The resulting size is reported as size on the created key.
Supported combinations: GPG + ED25519, GPG + RSA, RSA + RSA. Pairing
type: RSA with algorithm: ED25519 is rejected with 400.
Underlying cryptographic algorithm of a signing key. Known values include: RSA, ED25519, ECDSA. This field is extensible; clients must handle unknown values. Note that only RSA and ED25519 can be generated; ECDSA is only observed on imported keys.
RSAOptional expiration timestamp in Unix milliseconds
Human-readable name for the key
Cryptographic system of a signing key. Known values include: GPG (for Debian, RPM, Alpine), RSA (for direct signing operations). This field is extensible; clients must handle unknown values.
GPGSigning key details
Error response.
POST /api/v3/signing-keys/generate?account_identifier=text HTTP/1.1
Content-Type: application/json
Accept: */*
Content-Length: 63
{
"algorithm": "RSA",
"expirationAt": 1,
"name": "text",
"type": "GPG"
}{
"data": {
"algorithm": "RSA",
"createdAt": 1736360000123,
"createdBy": {
"display_name": "text",
"email": "text",
"type": "text",
"uid": "text"
},
"expirationAt": 1,
"fingerprint": "text",
"id": "123e4567-e89b-12d3-a456-426614174000",
"longKeyId": "text",
"modifiedAt": 1736360000123,
"name": "text",
"shortKeyId": "text",
"size": 1,
"source": "GENERATED",
"status": "ACTIVE",
"type": "GPG",
"updatedBy": {
"display_name": "text",
"email": "text",
"type": "text",
"uid": "text"
}
}
}Imports an existing signing key from Harness Secret Manager by validating it and storing metadata in the database. The private key remains in the user-provided secret reference (not copied).
Unique identifier for the Harness account.
Unique identifier for the organization within the account.
Example: default or engineering_org
Unique identifier for the project within the organization.
Example: my_project or frontend_services
Request to import an existing signing key from secret manager. type is the cryptographic system of the key being imported.
Passphrase-protected keys are supported for both GPG and RSA. Supply passphraseSecretIdentifier and passphraseSecretSpacePath together; providing only one is rejected with 400. The passphrase is stored as a secret reference and re-read on every signing operation, so it must remain readable for the lifetime of the key.
Accepted RSA private key encodings:
- PKCS#1 (
RSA PRIVATE KEY), encrypted or not - PKCS#8 (
PRIVATE KEY/ENCRYPTED PRIVATE KEY) - OpenSSH (
OPENSSH PRIVATE KEY), encrypted or not
Optional expiration timestamp in Unix milliseconds. Priority: provided value > key's embedded expiration > no expiration. Note: RSA keys don't have embedded expiration, so this is the only way to set expiration for RSA keys.
Human-readable name for the key
Reference to the passphrase secret. Required when the private key is encrypted, for both GPG and RSA keys, and must be provided together with passphraseSecretSpacePath.
Space path for the passphrase secret (e.g., "accountId/orgId/projectId"). Must be provided together with passphraseSecretIdentifier; defaults to the private key's space when omitted.
Reference to private key secret in Harness Secret Manager
Space path for the private key secret (e.g., "accountId/orgId/projectId")
Cryptographic system of a signing key. Known values include: GPG (for Debian, RPM, Alpine), RSA (for direct signing operations). This field is extensible; clients must handle unknown values.
GPGSigning key details
Error response.
POST /api/v3/signing-keys/import?account_identifier=text HTTP/1.1
Content-Type: application/json
Accept: */*
Content-Length: 187
{
"expirationAt": 1,
"name": "text",
"passphraseSecretIdentifier": "text",
"passphraseSecretSpacePath": "text",
"privateKeySecretIdentifier": "text",
"privateKeySecretSpacePath": "text",
"type": "GPG"
}{
"data": {
"algorithm": "RSA",
"createdAt": 1736360000123,
"createdBy": {
"display_name": "text",
"email": "text",
"type": "text",
"uid": "text"
},
"expirationAt": 1,
"fingerprint": "text",
"id": "123e4567-e89b-12d3-a456-426614174000",
"longKeyId": "text",
"modifiedAt": 1736360000123,
"name": "text",
"shortKeyId": "text",
"size": 1,
"source": "GENERATED",
"status": "ACTIVE",
"type": "GPG",
"updatedBy": {
"display_name": "text",
"email": "text",
"type": "text",
"uid": "text"
}
}
}Returns aggregate signing key counts for the requested scope: the total number of keys, the number of registries referencing a key in that scope, and the number of ACTIVE keys expiring within the next 30 days.
Counts apply to the requested scope only — they are not rolled up from parent or child scopes.
Unique identifier for the Harness account.
Unique identifier for the organization within the account.
Example: default or engineering_org
Unique identifier for the project within the organization.
Example: my_project or frontend_services
Aggregate signing key counts for the requested scope
Error response.
GET /api/v3/signing-keys/summary?account_identifier=text HTTP/1.1
Accept: */*
{
"data": {
"expiringSoon": 2,
"referencedRegistries": 4,
"totalKeys": 16
}
}Last updated
Was this helpful?