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.
- For use cases and a conceptual overview, see The Confidential HTTP Capability
- Guide: Making Confidential Requests
Quick reference
| Method | Description |
|---|---|
client.SendRequest | Makes 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 | *HTTPRequest | The HTTP request to execute inside the enclave. See HTTPRequest. |
VaultDonSecrets | []*SecretIdentifier | List of secrets to fetch from the Vault DON and make available in the enclave. See SecretIdentifier. |
confidentialhttp.HTTPRequest
Defines the HTTP request that will be executed inside the enclave.
Field | Type | Description |
|---|---|---|
Url | string | The URL of the API endpoint. |
Method | string | The HTTP method (e.g., "GET", "POST"). |
Body | isHTTPRequest_Body | The request body. Use HTTPRequest_BodyString for string templates or HTTPRequest_BodyBytes for raw bytes. |
MultiHeaders | map[string]*HeaderValues | Request headers. Supports multiple values per key and template syntax for secret injection. |
TemplatePublicValues | map[string]string | Public (non-secret) values used to fill template placeholders in the body and headers. |
CustomRootCaCertPem | []byte | Optional custom root CA certificate (PEM format) for verifying the external server's TLS certificate. |
Timeout | *durationpb.Duration | Optional request timeout. |
EncryptOutput | bool | If 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.
| Field | Type | Description |
|---|---|---|
StatusCode | uint32 | The HTTP status code. |
Body | []byte | The response body. If EncryptOutput is true, this contains the encrypted body (see Response encryption). |
MultiHeaders | map[string]*HeaderValues | The HTTP response headers. |
confidentialhttp.SecretIdentifier
Identifies a secret stored in the Vault DON.
| Field | Type | Description |
|---|---|---|
Key | string | The logical name of the secret. Must match the template placeholder (e.g., "myApiKey" matches {{.myApiKey}}). |
Namespace | string | The secret namespace. |
Owner | *string | Optional. The owner address for the secret. |
confidentialhttp.HeaderValues
Represents multiple values for a single HTTP header key.
| Field | Type | Description |
|---|---|---|
Values | []string | The 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: Thecre.Runtimefrom your trigger callback.input: A*ConfidentialHTTPRequestcontaining 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.
EncryptOutput | Secret key provided | Behavior |
|---|---|---|
false (default) | — | Response returned unencrypted. |
true | san_marino_aes_gcm_encryption_key in VaultDonSecrets | Response AES-GCM encrypted with your symmetric key. |
true | No key provided | Response 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.