Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/config/sidebar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,14 @@ export const SIDEBAR: Partial<Record<Sections, SectionEntry[]>> = {
"cre/guides/workflow/using-http-client/submitting-reports-http-go",
],
},
{
title: "Verifying CRE Reports Offchain",
url: "cre/guides/workflow/using-http-client/verifying-reports-offchain",
highlightAsCurrent: [
"cre/guides/workflow/using-http-client/verifying-reports-offchain-ts",
"cre/guides/workflow/using-http-client/verifying-reports-offchain-go",
],
},
],
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ metadata:

import { Aside } from "@components"

This guide shows how to manually generate a report containing a single value (like `uint256`, `address`, or `bool`). This is useful when you need to send a simple value onchain but don't have a struct or binding helper available.
This guide shows how to manually generate a **[CRE report](/cre/key-terms#report-cre-report)** containing a single value (like `uint256`, `address`, or `bool`). See [Key Terms: Report](/cre/key-terms#report-cre-report) for the full definition; in short, it is a DON-signed package from [`runtime.GenerateReport()`](/cre/guides/workflow/using-evm-client/onchain-write/generating-reports-single-values) / [`runtime.report()`](/cre/reference/sdk/core-ts#runtime-and-noderuntime) with your encoded data, workflow metadata, and signatures.

This guide covers **creating** the signed report ([`runtime.GenerateReport()`](/cre/guides/workflow/using-evm-client/onchain-write/generating-reports-single-values) / [`runtime.report()`](/cre/reference/sdk/core-ts#runtime-and-noderuntime)). **Delivering** it is a separate step: see the table below.

**Use this approach when:**

Expand All @@ -29,12 +31,14 @@ This guide shows how to manually generate a report containing a single value (li
Manually generating a report for a single value involves two main steps:

1. **ABI-encode the value** into bytes using the `go-ethereum/accounts/abi` package
1. **Generate a cryptographically signed report** using `runtime.GenerateReport()`
1. **Generate a cryptographically signed report** using [`runtime.GenerateReport()`](/cre/guides/workflow/using-evm-client/onchain-write/generating-reports-single-values)

The resulting report can then be:
| After [`GenerateReport()`](/cre/guides/workflow/using-evm-client/onchain-write/generating-reports-single-values) / [`report()`](/cre/reference/sdk/core-ts#runtime-and-noderuntime) | Guide | Who verifies? |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- |
| [`WriteReport()`](/cre/reference/sdk/evm-client-go#writereport) / [`writeReport()`](/cre/reference/sdk/evm-client-ts#writereport) | [Submitting Reports Onchain](/cre/guides/workflow/using-evm-client/onchain-write/submitting-reports-onchain) | `KeystoneForwarder` onchain |
| [`SendReport()`](/cre/reference/sdk/http-client-go#sendrequestersendreport) / [`sendReport()`](/cre/reference/sdk/http-client-ts#using-sendreport) | [Submitting Reports via HTTP](/cre/guides/workflow/using-http-client/submitting-reports-http) | Receiver: [Verifying CRE Reports Offchain](/cre/guides/workflow/using-http-client/verifying-reports-offchain) or your API |

- Submitted to the blockchain via `evm.Client.WriteReport()` (see [Submitting Reports Onchain](/cre/guides/workflow/using-evm-client/onchain-write/submitting-reports-onchain))
- Sent to an HTTP endpoint via `http.Client` (see [Submitting Reports via HTTP](/cre/guides/workflow/using-http-client/submitting-reports-http))
See [API Interactions: CRE reports over HTTP](/cre/guides/workflow/using-http-client#cre-reports-over-http) for the sender → receiver mental model.

<Aside type="note" title="Have a struct in your contract's ABI?">
If your struct appears in a public/external function's signature, you can use the simpler `WriteReportFrom<StructName>()` helper instead. See [Using WriteReportFrom Helpers](/cre/guides/workflow/using-evm-client/onchain-write/using-write-report-helpers).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ metadata:

import { Aside } from "@components"

This guide shows how to generate a report containing a struct with multiple fields. There are two approaches depending on whether you have generated bindings for your contract.
This guide shows how to generate a **[CRE report](/cre/key-terms#report-cre-report)** containing a struct with multiple fields. See [Key Terms: Report](/cre/key-terms#report-cre-report) for the full definition. After generation, deliver it [onchain](/cre/guides/workflow/using-evm-client/onchain-write/submitting-reports-onchain) or via [HTTP](/cre/guides/workflow/using-http-client/submitting-reports-http); HTTP receivers should [verify offchain](/cre/guides/workflow/using-http-client/verifying-reports-offchain). See [API Interactions: CRE reports over HTTP](/cre/guides/workflow/using-http-client#cre-reports-over-http).

There are two encoding approaches depending on whether you have generated bindings for your contract.

## Choosing your approach

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,17 @@ Here's the journey your workflow's data takes to reach the blockchain:

Your workflow code handles this process using the [`evm.Client`](/cre/reference/sdk/evm-client), which manages the interaction with the Forwarder contract. Depending on your approach (covered below), this can be fully automated via generated binding helpers or done manually with direct client calls.

### Where reports can go after generation

The same signed report from `runtime.GenerateReport()` can be delivered in different ways:

| Destination | Guide | Verification |
| ------------------------------ | --------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| Smart contract (via Forwarder) | This section + [Submitting Reports Onchain](/cre/guides/workflow/using-evm-client/onchain-write/submitting-reports-onchain) | Onchain in `KeystoneForwarder` |
| HTTP API | [Submitting Reports via HTTP](/cre/guides/workflow/using-http-client/submitting-reports-http-go) | [Verifying CRE Reports Offchain](/cre/guides/workflow/using-http-client/verifying-reports-offchain-go) on the receiver |

See [API Interactions: CRE reports over HTTP](/cre/guides/workflow/using-http-client#cre-reports-over-http) for the sender → receiver flow.

{/* prettier-ignore */}
<Aside type="caution" title="Replay attacks">
Signed reports can be replayed on a different chain or resubmitted on the same chain after a revert. For any workflow that performs state-changing actions, you must embed protective metadata in the report payload and verify it in your consumer contract. See [Replay attacks](/cre/guides/workflow/using-evm-client/onchain-write/building-consumer-contracts#replay-attacks) for full examples.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,17 @@ Here's the journey your workflow's data takes to reach the blockchain:

In your workflow code, this process involves two steps: calling `runtime.report()` to generate the signed report, then calling `evmClient.writeReport()` to submit it to the blockchain.

### Where reports can go after generation

The same signed report from `runtime.report()` can be delivered in different ways:

| Destination | Guide | Verification |
| ------------------------------ | --------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| Smart contract (via Forwarder) | This section + [Submitting Reports Onchain](/cre/guides/workflow/using-evm-client/onchain-write/submitting-reports-onchain) | Onchain in `KeystoneForwarder` |
| HTTP API | [Submitting Reports via HTTP](/cre/guides/workflow/using-http-client/submitting-reports-http-ts) | [Verifying CRE Reports Offchain](/cre/guides/workflow/using-http-client/verifying-reports-offchain-ts) on the receiver |

See [API Interactions: CRE reports over HTTP](/cre/guides/workflow/using-http-client#cre-reports-over-http) for the sender → receiver flow.

## What you need: A consumer contract

Before you can write data onchain, you need a **consumer contract**. This is the smart contract that will receive your workflow's data.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@ metadata:

import { Aside } from "@components"

This guide shows how to manually submit a generated report to the blockchain using the low-level `evm.Client.WriteReport()` method.
This guide shows how to manually submit a generated **CRE report** to the blockchain using the low-level `evm.Client.WriteReport()` method. The forwarder verifies signatures onchain: no separate [offchain verification](/cre/guides/workflow/using-http-client/verifying-reports-offchain) step.

{/* prettier-ignore */}
<Aside type="note" title="HTTP delivery instead?">
If you need to POST the report to an API rather than a contract, generate the report the same way ([single values](/cre/guides/workflow/using-evm-client/onchain-write/generating-reports-single-values) or [structs](/cre/guides/workflow/using-evm-client/onchain-write/generating-reports-structs)), then follow [Submitting Reports via HTTP](/cre/guides/workflow/using-http-client/submitting-reports-http). See [API Interactions: CRE reports over HTTP](/cre/guides/workflow/using-http-client#cre-reports-over-http).
</Aside>

**Use this approach when:**

Expand Down
18 changes: 14 additions & 4 deletions src/content/cre/guides/workflow/using-http-client/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ isIndex: true
metadata:
description: "Connect your workflow to external APIs: learn to make GET and POST requests with built-in consensus for secure offchain data."
datePublished: "2025-11-04"
lastModified: "2026-03-17"
lastModified: "2026-05-20"
---

import { Aside } from "@components"
Expand All @@ -20,13 +20,23 @@ The CRE SDK provides an HTTP client that allows your workflows to interact with

{/* prettier-ignore */}
<Aside type="caution" title="Parse responses before aggregation">
When using a numeric aggregation method (such as `median`), always parse the HTTP response **inside** your node function and return a numeric value never pass the raw response body to the aggregation step. If your endpoint returns an error string and your node function passes that string to a median aggregation, consensus will fail with `unsupported type for median aggregation`. See the [best practices section](/cre/guides/workflow/using-http-client/get-request#best-practices) of the GET request guide for correct and incorrect patterns.
When using a numeric aggregation method (such as `median`), always parse the HTTP response **inside** your node function and return a numeric value: never pass the raw response body to the aggregation step. If your endpoint returns an error string and your node function passes that string to a median aggregation, consensus will fail with `unsupported type for median aggregation`. See the [best practices section](/cre/guides/workflow/using-http-client/get-request#best-practices) of the GET request guide for correct and incorrect patterns.
</Aside>

These guides will walk you through the common use cases for the HTTP client.

## Guides

- **[Making GET Requests](/cre/guides/workflow/using-http-client/get-request)**: Learn how to fetch data from a public API using a `GET` request.
- **[Making POST Requests](/cre/guides/workflow/using-http-client/post-request)**: Learn how to send data to an external endpoint using a `POST` request.
- **[Submitting Reports via HTTP](/cre/guides/workflow/using-http-client/submitting-reports-http)**: Learn how to submit cryptographically signed reports to an external HTTP endpoint.
- **[Verifying CRE Reports Offchain](/cre/guides/workflow/using-http-client/verifying-reports-offchain)**: Verify report signatures and read workflow metadata when receiving reports over HTTP or other offchain channels.

## CRE reports over HTTP

A **[CRE report](/cre/key-terms#report-cre-report)** is a DON-signed package your workflow creates with [`runtime.report()`](/cre/reference/sdk/core-ts#runtime-and-noderuntime) (TypeScript) or [`runtime.GenerateReport()`](/cre/guides/workflow/using-evm-client/onchain-write/generating-reports-single-values) (Go). It bundles your encoded payload, workflow metadata, report context, and cryptographic signatures from the DON. See [Key Terms: Report](/cre/key-terms#report-cre-report) for the full definition, including how onchain delivery differs from HTTP.

A typical secure integration uses two parties:

1. **Sender:** a CRE workflow that runs your logic, signs a report, and POSTs it to a URL. See [Submitting Reports via HTTP](/cre/guides/workflow/using-http-client/submitting-reports-http).
2. **Receiver:** your API or another CRE workflow that verifies the report before using the data. See [Verifying CRE Reports Offchain](/cre/guides/workflow/using-http-client/verifying-reports-offchain).

The sender creates the report inside the workflow; the receiver must verify signatures before trusting the payload.
Loading
Loading