SDK Reference: HTTP Client
The HTTP Client lets you make requests to external APIs from your workflow. Each node in the DON executes the request independently, and the SDK uses consensus to provide a single, reliable result.
Common use cases:
- Fetching data from REST APIs (GET requests)
- Sending data to webhooks (POST requests)
- Submitting reports to offchain systems (Report submission)
Quick reference
| Method | Use When | Guide |
|---|---|---|
http.SendRequest | Making HTTP calls (recommended) | GET / POST |
client.SendRequest | Complex scenarios requiring fine control | GET |
sendRequester.SendReport | Submitting reports via HTTP (recommended) | Report submission |
client.SendReport | Complex report submission scenarios | Report submission |
Core types
http.Request
Defines the parameters for an outgoing HTTP request.
Field | Type | Description |
|---|---|---|
Url | string | The URL of the API endpoint. |
Method | string | The HTTP method (e.g., "GET", "POST"). |
Headers | map[string]string | Optional HTTP headers. |
Body | []byte | Optional raw request body. |
Timeout | *durationpb.Duration | Optional request timeout duration. Set using durationpb.New(), e.g., durationpb.New(30 * time.Second) for 30 seconds. |
CacheSettings | *CacheSettings | Optional caching behavior for the request. |
http.Response
The result of the HTTP call from a single node. If the request fails, the error is returned by the .Await() call on the Promise.
| Field | Type | Description |
|---|---|---|
StatusCode | uint32 | The HTTP status code. |
Headers | map[string]string | The HTTP response headers. |
Body | []byte | The raw response body. |
http.CacheSettings
Defines caching behavior for the request. This is particularly useful for preventing duplicate execution of non-idempotent requests (POST, PUT, PATCH, DELETE).
Field | Type | Description |
|---|---|---|
Store | bool | If true, store the response in the cache for potential reuse by other nodes. |
MaxAge | *durationpb.Duration | Maximum age of a cached response that this workflow will accept. If zero or nil, the request will not attempt to read from cache (but may still store if Store is true). Max value is 10 minutes. |
Understanding CacheSettings behavior
When you make HTTP requests in CRE, all nodes in the DON execute the request by default. For read-only operations (like GET), this is fineāconsensus ensures a reliable result. However, for non-idempotent operations (POST, PUT, PATCH, DELETE), multiple executions can cause problems:
- Creating duplicate resources (e.g., multiple user accounts)
- Triggering duplicate actions (e.g., sending multiple emails)
- Unintended side effects (e.g., incrementing counters multiple times)
CacheSettings provides a solution by enabling a shared cache across all nodes in the DON:
- Node 1 makes the HTTP request and stores the response in the shared cache
- Nodes 2, 3, etc. check the cache first and reuse the cached response if it exists
Important considerations:
-
Best effort mechanism: The caching works reliably in most scenarios, but is not guaranteed to prevent all duplicates. For example, gateway availability (network issues or deployments) can affect routing to different gateway instances.
-
Request matching: Caching only works when all nodes construct identical requests (same URL, headers, and body). Ensure your workflow generates deterministic request payloads.
-
Understanding
MaxAge: This controls how stale your workflow will accept a cached response to be:- The cache system stores responses for up to 10 minutes by default (system-wide TTL)
MaxAgelets your workflow specify: "I'll only use cached data if it's fresher than X duration"- Set
MaxAgeusingdurationpb.New(), for example:durationpb.New(60 * time.Second)for 60 seconds - Setting
MaxAgetonilor zero forces a fresh fetch every time (but still stores ifStoreis true) - For POST/PUT/PATCH/DELETE operations: Set this slightly longer than your workflow's expected execution time
- For GET operations where you want to reuse data: Set this to your desired cache duration
For practical examples, see the POST request guide.
Making HTTP requests
http.SendRequest
The recommended, high-level helper for making HTTP requests. Automatically handles the cre.RunInNodeMode pattern.
Signature:
func SendRequest[C, T any](
config C,
runtime cre.Runtime,
client *Client,
fn func(config C, logger *slog.Logger, sendRequester *SendRequester) (T, error),
ca cre.ConsensusAggregation[T],
) cre.Promise[T]
Parameters:
config: Your workflow's configuration struct, passed tofnruntime: The top-levelcre.Runtimefrom your trigger callbackclient: An initialized*http.Clientfn: Your request logic function that receivesconfig,logger, andsendRequesterca: The consensus aggregation method
Example:
func fetchData(config *Config, logger *slog.Logger, sendRequester *http.SendRequester) (*Data, error) {
resp, err := sendRequester.SendRequest(&http.Request{
Url: config.ApiUrl,
Method: "GET",
}).Await()
if err != nil {
return nil, err
}
// Parse and return...
}
// In your trigger callback
result, err := http.SendRequest(config, runtime, client,
fetchData,
cre.ConsensusAggregationFromTags[*Data](),
).Await()
Guides:
client.SendRequest
The lower-level method for complex scenarios. Must be manually wrapped in cre.RunInNodeMode.
Signature:
func (c *Client) SendRequest(runtime cre.NodeRuntime, input *http.Request) cre.Promise[*http.Response]
Parameters:
runtime: Acre.NodeRuntimeprovided bycre.RunInNodeModeinput: An*http.Requeststruct
Returns:
cre.Promise[*http.Response]
Guide:
Submitting reports via HTTP
These methods send cryptographically signed reports (generated via runtime.GenerateReport()) to an HTTP endpoint. For a comprehensive guide including transformation function patterns and best practices, see Submitting Reports via HTTP.
sendRequester.SendReport
The recommended, high-level method for submitting reports via HTTP.
Signature:
func (c *SendRequester) SendReport(
report cre.Report,
fn func(*sdk.ReportResponse) (*http.Request, error)
) cre.Promise[*http.Response]
Parameters:
report: Thecre.Reportobject generated byruntime.GenerateReport()fn: A transformation function that formats the report for your API. Receives*sdk.ReportResponseand returns*http.Request.
Returns:
cre.Promise[*http.Response]
Example:
func formatReport(r *sdk.ReportResponse) (*http.Request, error) {
return &http.Request{
Url: "https://api.example.com/reports",
Method: "POST",
Body: r.RawReport,
CacheSettings: &http.CacheSettings{
Store: true,
MaxAge: durationpb.New(5 * time.Minute),
},
}, nil
}
resp, err := sendRequester.SendReport(report, formatReport).Await()
Guide:
client.SendReport
The lower-level version for complex scenarios. Must be manually wrapped in cre.RunInNodeMode.
Signature:
func (c *Client) SendReport(
runtime cre.NodeRuntime,
report cre.Report,
fn func(*sdk.ReportResponse) (*http.Request, error)
) cre.Promise[*http.Response]
Parameters:
runtime: Acre.NodeRuntimeprovided bycre.RunInNodeModereport: Thecre.Reportobject generated byruntime.GenerateReport()fn: A transformation function that formats the report for your API
Returns:
cre.Promise[*http.Response]
Guide:
Report types
These types are specific to report submission via HTTP.
sdk.ReportResponse
The internal structure of a report generated by runtime.GenerateReport(). This type is passed to your transformation function when using SendReport. It contains the encoded report data plus cryptographic signatures from the DON.
Field | Type | Description |
|---|---|---|
RawReport | []byte | The complete report in binary format, including metadata and your ABI-encoded payload. This is the primary data you'll send to your API. |
ReportContext | []byte | Additional context data about the report (workflow execution details). Some APIs may require this to be included alongside the report. |
Sigs | []*sdk.AttributedSignature | Array of cryptographic signatures from DON nodes. Each signature proves that a node validated and agreed on the report content. |
ConfigDigest | []byte | Configuration digest identifying the DON configuration that generated this report. |
SeqNr | uint64 | Sequence number of this report within the workflow execution. |
Example - Accessing report fields:
func myTransformFunction(r *sdk.ReportResponse) (*http.Request, error) {
logger.Info("Report details",
"seqNr", r.SeqNr,
"numSignatures", len(r.Sigs),
"reportSize", len(r.RawReport),
)
// Most APIs want the raw report in the body
return &http.Request{
Url: "https://api.example.com/reports",
Method: "POST",
Body: r.RawReport,
}, nil
}
sdk.AttributedSignature
Represents a single signature from a DON node on a report.
| Field | Type | Description |
|---|---|---|
Signature | []byte | The cryptographic signature bytes. |
SignerId | uint32 | The unique identifier of the node that created this signature. |
Example - Accessing signatures:
func formatReport(r *sdk.ReportResponse) (*http.Request, error) {
// Access signatures
for i, sig := range r.Sigs {
logger.Info("Signature", "index", i, "signerId", sig.SignerId, "length", len(sig.Signature))
}
// Format for your API...
}
For complete examples of including signatures in different formats (body, headers, JSON), see the Submitting Reports via HTTP guide.