SDK Reference: Confidential HTTP Client

The Confidential HTTP Client lets you make privacy-preserving requests to external APIs from your workflow. Unlike the regular http.Client, the request executes inside a secure enclave, secrets are injected via templates, and responses can be optionally encrypted.

Quick reference

MethodDescription
client.SendRequestMakes a confidential HTTP request.

Core types

confidentialhttp.ConfidentialHTTPRequest

The top-level request type that combines an HTTP request with Vault DON secrets and encryption settings.

Field
Type
Description
Request*HTTPRequestThe HTTP request to execute inside the enclave. See HTTPRequest.
VaultDonSecrets[]*SecretIdentifierVault DON secrets for enclave-only {{.key}} substitution in the request (SecretIdentifier). Use this when credentials or other sensitive template values must stay out of Workflow DON execution—not replaceable by pasting runtime.GetSecret() output into headers or body. See what stays confidential and Making Confidential Requests.

confidentialhttp.HTTPRequest

Defines the HTTP request that will be executed inside the enclave.

Field
Type
Description
UrlstringThe URL of the API endpoint.
MethodstringThe HTTP method (e.g., "GET", "POST").
BodyisHTTPRequest_BodyThe request body. Use HTTPRequest_BodyString for string templates or HTTPRequest_BodyBytes for raw bytes.
MultiHeadersmap[string]*HeaderValuesRequest headers. Supports multiple values per key and template syntax for secret injection.
TemplatePublicValuesmap[string]stringPublic (non-secret) values used to fill template placeholders in the body and headers.
CustomRootCaCertPem[]byteOptional custom root CA certificate (PEM format) for verifying the external server's TLS certificate.
Timeout*durationpb.DurationOptional request timeout.
EncryptOutputboolIf true, encrypts the response body before it leaves the enclave. See Response encryption. Default: false.

Setting the request body

The Body field is a oneof type with two options:

String template (recommended for secret injection):

Body: &confidentialhttp.HTTPRequest_BodyString{
	BodyString: `{"auth": "{{.myApiKey}}", "action": "getData"}`,
},

Raw bytes:

Body: &confidentialhttp.HTTPRequest_BodyBytes{
	BodyBytes: []byte(`{"action": "getData"}`),
},

confidentialhttp.HTTPResponse

The response returned from the enclave after the HTTP request completes.

FieldTypeDescription
StatusCodeuint32The HTTP status code.
Body[]byteThe response body. If EncryptOutput is true, this contains the encrypted body (see Response encryption).
MultiHeadersmap[string]*HeaderValuesThe HTTP response headers.

confidentialhttp.SecretIdentifier

Identifies a secret stored in the Vault DON.

FieldTypeDescription
KeystringThe logical name of the secret. Must match the template placeholder (e.g., "myApiKey" matches {{.myApiKey}}).
NamespacestringThe secret namespace.
Owner*stringOptional. The owner address for the secret.

confidentialhttp.HeaderValues

Represents multiple values for a single HTTP header key.

FieldTypeDescription
Values[]stringThe header values. Supports template syntax for secret injection (e.g., "Basic {{.myToken}}").

Making requests

client.SendRequest

Makes a confidential HTTP request. The request executes inside a secure enclave, so unlike the regular HTTP client, there is no need to wrap this call in cre.RunInNodeMode.

Signature:

func (c *Client) SendRequest(runtime cre.Runtime, input *ConfidentialHTTPRequest) cre.Promise[*HTTPResponse]

Parameters:

  • runtime: The cre.Runtime from your trigger callback.
  • input: A *ConfidentialHTTPRequest containing the request and secrets.

Returns:

  • cre.Promise[*HTTPResponse]

Example:

client := &confidentialhttp.Client{}
resp, err := client.SendRequest(runtime, &confidentialhttp.ConfidentialHTTPRequest{
	Request: &confidentialhttp.HTTPRequest{
		Url:    config.URL,
		Method: "POST",
		Body:   &confidentialhttp.HTTPRequest_BodyString{BodyString: `{"auth": "{{.apiKey}}"}`},
		MultiHeaders: map[string]*confidentialhttp.HeaderValues{
			"Content-Type":  {Values: []string{"application/json"}},
			"Authorization": {Values: []string{"Basic {{.apiKey}}"}},
		},
		EncryptOutput: false,
	},
	VaultDonSecrets: []*confidentialhttp.SecretIdentifier{
		{Key: "apiKey"},
	},
}).Await()
if err != nil {
	return Result{}, err
}
// Parse resp.Body...

Guide: Making Confidential Requests

Template syntax

Secrets are injected into the request body and headers using Go template syntax: {{.secretName}}. The placeholder name must match the Key field in the corresponding SecretIdentifier.

Body template:

Body: &confidentialhttp.HTTPRequest_BodyString{
	BodyString: `{"apiKey": "{{.myApiKey}}", "method": "{{.method}}", "params": []}`,
},

Header template:

MultiHeaders: map[string]*confidentialhttp.HeaderValues{
	"Authorization": {Values: []string{"Basic {{.myCredential}}"}},
},

TemplatePublicValues (optional)

Every {{.placeholder}} in your body or headers is resolved inside the enclave. By default, placeholders are filled with secrets from VaultDonSecrets. But sometimes you have a placeholder value that isn't secret — for example, an RPC method name or a public parameter. That's what TemplatePublicValues is for: it lets you inject non-secret values into the same template.

This is purely a convenience. You could always hardcode the value directly in the body string instead:

// These two are equivalent:

// Option 1: hardcoded in the body string
Body: &confidentialhttp.HTTPRequest_BodyString{BodyString: `{"method": "eth_blockNumber", "auth": "{{.apiKey}}"}`}

// Option 2: using TemplatePublicValues
Body: &confidentialhttp.HTTPRequest_BodyString{BodyString: `{"method": "{{.method}}", "auth": "{{.apiKey}}"}`}
TemplatePublicValues: map[string]string{"method": "eth_blockNumber"}

TemplatePublicValues is useful when you want to keep the template generic and pass in dynamic values (e.g., from config) without string concatenation.

Example with both secret and public values:

Request: &confidentialhttp.HTTPRequest{
	Url:    config.URL,
	Method: "POST",
	Body:   &confidentialhttp.HTTPRequest_BodyString{BodyString: `{"method": "{{.rpcMethod}}", "auth": "{{.apiKey}}"}`},
	TemplatePublicValues: map[string]string{
		"rpcMethod": config.RPCMethod,   // dynamic value from config, not a secret
	},
},
VaultDonSecrets: []*confidentialhttp.SecretIdentifier{
	{Key: "apiKey"},   // secret, from Vault DON
},

In this example, {{.rpcMethod}} is resolved from TemplatePublicValues (a dynamic, non-secret value from your workflow config) and {{.apiKey}} is resolved from the Vault DON (a secret). Both are resolved inside the enclave.

Response encryption

The EncryptOutput field controls whether the response body is encrypted before leaving the enclave.

EncryptOutputSecret key providedBehavior
false (default)Response returned unencrypted.
truesan_marino_aes_gcm_encryption_key in VaultDonSecretsResponse AES-GCM encrypted with your symmetric key.
trueNo key providedResponse TDH2 encrypted with the Vault DON master public key.

AES-GCM encryption is the recommended approach. Store a 256-bit (32-byte) AES key as a Vault DON secret with the identifier san_marino_aes_gcm_encryption_key, then decrypt the response in your own secure backend.

The encrypted response body is structured as nonce || ciphertext || tag.

For a complete decryption example, see the Making Confidential Requests guide.

Get the latest Chainlink content straight to your inbox.