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:

Quick reference

MethodUse WhenGuide
http.SendRequestMaking HTTP calls (recommended)GET / POST
client.SendRequestComplex scenarios requiring fine controlGET
sendRequester.SendReportSubmitting reports via HTTP (recommended)Report submission
client.SendReportComplex report submission scenariosReport submission

Core types

http.Request

Defines the parameters for an outgoing HTTP request.

Field
Type
Description
UrlstringThe URL of the API endpoint.
MethodstringThe HTTP method (e.g., "GET", "POST").
Headersmap[string]stringOptional HTTP headers.
Body[]byteOptional raw request body.
Timeout*durationpb.DurationOptional request timeout duration. Set using durationpb.New(), e.g., durationpb.New(30 * time.Second) for 30 seconds.
CacheSettings*CacheSettingsOptional 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.

FieldTypeDescription
StatusCodeuint32The HTTP status code.
Headersmap[string]stringThe HTTP response headers.
Body[]byteThe 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
StoreboolIf true, store the response in the cache for potential reuse by other nodes.
MaxAge*durationpb.DurationMaximum 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:

  1. Node 1 makes the HTTP request and stores the response in the shared cache
  2. 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)
    • MaxAge lets your workflow specify: "I'll only use cached data if it's fresher than X duration"
    • Set MaxAge using durationpb.New(), for example: durationpb.New(60 * time.Second) for 60 seconds
    • Setting MaxAge to nil or zero forces a fresh fetch every time (but still stores if Store is 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 to fn
  • runtime: The top-level cre.Runtime from your trigger callback
  • client: An initialized *http.Client
  • fn: Your request logic function that receives config, logger, and sendRequester
  • ca: 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: A cre.NodeRuntime provided by cre.RunInNodeMode
  • input: An *http.Request struct

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: The cre.Report object generated by runtime.GenerateReport()
  • fn: A transformation function that formats the report for your API. Receives *sdk.ReportResponse and 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: A cre.NodeRuntime provided by cre.RunInNodeMode
  • report: The cre.Report object generated by runtime.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[]byteThe complete report in binary format, including metadata and your ABI-encoded payload. This is the primary data you'll send to your API.
ReportContext[]byteAdditional context data about the report (workflow execution details). Some APIs may require this to be included alongside the report.
Sigs[]*sdk.AttributedSignatureArray of cryptographic signatures from DON nodes. Each signature proves that a node validated and agreed on the report content.
ConfigDigest[]byteConfiguration digest identifying the DON configuration that generated this report.
SeqNruint64Sequence 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.

FieldTypeDescription
Signature[]byteThe cryptographic signature bytes.
SignerIduint32The 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.

Get the latest Chainlink content straight to your inbox.