Registers or rotates the AGENT-scoped caller's active RSA public key. The private key stays on the agent runtime and never traverses the server.
For new agents, the Platform wizard already generates the runtime key pair in
the browser, registers the public key, applies selected security groups, and
puts the private key in the one-time runtime JSON. Normal r4 configure agent --config <path> and r4 project env PROJECT_ID flows should use that JSON
directly and do not need to call this endpoint.
POST /api/v1/machine/vault/public-key| Header | Type | Required | Description |
|---|---|---|---|
X-API-Key | string | Yes | Your AGENT-scoped API key |
X-R4-Agent-Hostname | string | No | Best-effort runtime hostname claim from official SDK/runtime clients. Stored on the agent only for operator visibility |
{
"encryptionKeyId": "507f1f77bcf86cd799439015",
"publicKey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A...\n-----END PUBLIC KEY-----",
"previousEncryptionKeyId": "507f1f77bcf86cd799439010",
"rotationSignature": "base64-signature",
"rewrappedVaultKeys": [
{
"vaultId": "507f1f77bcf86cd799439011",
"encryptionKeyId": "507f1f77bcf86cd799439015",
"signerEncryptionKeyId": "507f1f77bcf86cd799439015",
"signerType": "AGENT_ENCRYPTION_KEY",
"dekVersion": 3,
"wrappedDek": "base64-ciphertext",
"wrappedDekSignature": "base64-signature"
}
]
}| Field | Type | Required | Description |
|---|---|---|---|
encryptionKeyId | string | No | Optional client-chosen ID for the new active encryption key. Required when rotating a key that still has active wrapped vault access |
publicKey | string | Yes | PEM-encoded RSA public key generated and stored locally by the agent |
previousEncryptionKeyId | string | No | Previous active agent key ID. Required when rotating to a different key |
rotationSignature | string | No | RSA-PSS signature from the previous private key approving the new public key |
rewrappedVaultKeys | array | No | Full replacement wrapped-DEK batch for every still-active vault assignment on the old key. Required when rotating away from a key that still has active wrapped vault access |
Success (201 Created)
{
"encryptionKeyId": "507f1f77bcf86cd799439015",
"publicKey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A...\n-----END PUBLIC KEY-----",
"fingerprint": "b5d44d6c7c1c1d4b8f31b1d9d8445d6c7c1c1d4b8f31b1d9d8445d6c7c1c1d4b",
"previousEncryptionKeyId": "507f1f77bcf86cd799439010",
"rotationSignature": "base64-signature"
}| Field | Type | Description |
|---|---|---|
encryptionKeyId | string | Active agent encryption key ID used as the wrapped-DEK recipient |
publicKey | string | PEM-encoded RSA public key currently active for the agent |
fingerprint | string | SHA-256 fingerprint of the public key |
previousEncryptionKeyId | string | null | Previous key ID for continuity verification |
rotationSignature | string | null | Continuity signature verifiable by the previous public key |
400 Bad Request - Rotation proof missing or invalid
{
"message": "Key rotation requires previousEncryptionKeyId and rotationSignature."
}400 Bad Request - Rotation missing the required re-wrap batch
{
"message": "Rotating an active agent key with wrapped vault access requires encryptionKeyId so the runtime can pre-sign replacement wrapped DEKs."
}403 Forbidden - Not an AGENT-scoped API key
{
"error": {
"code": "agent_scope_required",
"message": "This endpoint requires an AGENT-scoped API key."
}
}404 Not Found - Agent not found
{
"error": {
"code": "agent_not_found",
"message": "Agent not found or you do not have access to it."
}
}curl -X POST "https://r4.dev/api/v1/machine/vault/public-key" \
-H "X-API-Key: rk_abc123def456.ghijklmnopqrstuvwxyz" \
-H "Content-Type: application/json" \
-H "X-R4-Agent-Hostname: build-runner-01" \
-d '{
"publicKey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A...\n-----END PUBLIC KEY-----"
}'X-R4-Agent-Hostname claim on the agent so operators can see where the active runtime key most recently registeredrewrappedVaultKeys batch, and the backend archives the old wrapped-DEK rows plus the old key in one transactionr4 configure agent --config <path> or pass the API key and private key to the SDK.GET /vault/:vaultId/wrapped-key for the vault DEK encrypted to the agent's active key.GET /vault/:vaultId/public-keys to verify the wrapped-DEK signer.GET /vault/:vaultId/environment-fields, GET /vault/:vaultId/fields/:fieldId, or GET /vault/:vaultId/items/:itemId for the encrypted field payloads you need.If you are sending a different public key, include previousEncryptionKeyId and a rotationSignature from the current private key. If that old key still has active wrapped vault access, also include encryptionKeyId plus a rewrappedVaultKeys entry for every active vault DEK so the server can rotate and re-wrap atomically.