# Accessing a Public API

Data Requests allow you to retrieve information from public API endpoints that do not require sensitive credentials like API keys. For APIs that do require keys, see [Accessing a Private API](/home/for-developers/define-your-data-source/accessing-a-private-api.md).

In this walkthrough, we'll use the [SEDA Starter Kit](https://github.com/sedaprotocol/seda-starter-kit), which includes all necessary dependencies to build and test an Oracle Program.

## HTTP Fetch: GET

The `httpFetch` method is available only during the **execution** phase.

{% hint style="warning" %}
Attempting to use it in the tally phase will cause an error due to its non-deterministic nature.
{% endhint %}

Example using the `http_fetch` method:

```rust
use seda_sdk_rs::{http_fetch, log, oracle_program, Process};

#[oracle_program]
impl MyDataRequest {
    fn execute() {
        let response = http_fetch("https://pokeapi.co/api/v2/pokemon-species/mewtwo", None);

        if !response.is_ok() {
            Process::error("Could not fetch API endpoint".as_bytes());
            return;
        }
        let response_str = String::from_utf8(response.bytes).unwrap();
        log!("Response: {}", response_str);
    }

    fn tally() {
        panic!("Not implemented");
    }
}
```

Running this program with the following test will output the result of the execution, showing the `http_fetch` response as a string. You can place this test in `tests/my-dr.test.ts`:

```typescript
import { describe, it} from "bun:test";
import { file } from "bun";
import { testOracleProgramExecution } from "@seda-protocol/dev-tools"

describe("data request execution", () => {
  it("should run MyDataRequest", async () => {
    const wasmBinary = await file("target/wasm32-wasip1/release-wasm/oracle-program.wasm").arrayBuffer();

    // Locally executes the Data Request
    const vmResult = await testOracleProgramExecution(
      Buffer.from(wasmBinary),
      // This program doesn't have any inputs
      Buffer.from(""),
    );
    
    console.log(vmResult.stdout);
    console.error(vmResult.stderr);
  });
});
```

#### Testing the Data Request

Running the test will compile the binary and execute the test file, showing the output of the API formatted in JSON.

```sh
$ bun run test
```

Outputs:

```bash
bun test v1.2.5 (013fdddc)

tests/index.test.ts:
Response: [...]

✓ data request execution > should run MyDataRequest [1102.00ms]
```

#### Parsing JSON Responses

To make your Oracle Program more useful, you can parse the JSON response and work with its properties. You can use the `serde` crate to deserialize API responses into custom Rust structs.

Let’s modify our example:

```rust
use seda_sdk_rs::{http_fetch, log, oracle_program, Process};
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
struct Color {
    name: String,
}

#[derive(Serialize, Deserialize)]
struct PokemonSpecies {
    id: u32,
    name: String,
    color: Color,
    is_legendary: bool,
}

#[oracle_program]
impl MyDataRequest {
    fn execute() {
        let response = http_fetch("https://pokeapi.co/api/v2/pokemon-species/mewtwo", None);

        if !response.is_ok() {
            Process::error("Could not fetch API endpoint".as_bytes());
            return;
        }
        let species = serde_json::from_slice::<PokemonSpecies>(&response.bytes).unwrap();

        log!(
            "Pokemon: {} (ID: {}), Color: {}, Legendary: {}",
            species.name,
            species.id,
            species.color.name,
            species.is_legendary
        );
    }

    fn tally() {
        panic!("Not implemented");
    }
}
```

Running the previous test again now outputs:

```sh
bun test v1.2.5 (013fdddc)

tests/index.test.ts:
Pokemon: mewtwo (ID: 150), Color: purple, Legendary: true

✓ data request execution > should run MyDataRequest [723.00ms]
```

Now you can call any open API you want and process the data as needed.

## HTTP Fetch: POST

The SEDA SDK supports `POST`, `PATCH`, `PUT`, and other HTTP methods via `HttpFetchOptions`. You can attach headers and a request body — useful for working with GraphQL APIs or file uploads (e.g., IPFS).

Example sending JSON via POST:

```rust
use std::collections::BTreeMap;

use seda_sdk_rs::{
    bytes::{Bytes, ToBytes},
    elog, http_fetch, log, oracle_program, HttpFetchMethod, HttpFetchOptions, Process,
};
use serde_json::json;

#[oracle_program]
impl MyDataRequest {
    fn execute() {
        let query_body = json!({
            "key": "value_test"
        });

        let mut headers: BTreeMap<String, String> = BTreeMap::default();
        headers.insert("content-type".to_string(), "application/json".to_string());

        let body: Bytes = query_body.to_string().to_bytes();
        let response = http_fetch(
            "https://httpbin.org/post",
            Some(HttpFetchOptions {
                method: HttpFetchMethod::Post,
                headers,
                body: Some(body),
            }),
        );

        if !response.is_ok() {
            elog!("Error: {}", String::from_utf8_lossy(&response.bytes));
            Process::error("Could not fetch API endpoint".as_bytes());
            return;
        }

        log!("Success: {}", String::from_utf8(response.bytes).unwrap());
    }

    fn tally() {
        panic!("Not implemented");
    }
}
```

Running the test will give you the response of the POST request:

```sh
bun test v1.1.26 (0a37423b)

tests/index.test.mts:
Success: {
  "args": {}, 
  "data": "{\"key\":\"value_test\"}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate, br", 
    "Content-Length": "20", 
    "Content-Type": "application/json", 
    "Host": "httpbin.org", 
    "User-Agent": "Bun/1.2.5", 
  }, 
  "json": {
    "key": "value_test"
  }, 
  "origin": "REDACTED", 
  "url": "https://httpbin.org/post"
}
✓ data request execution > should run MyDataRequest [883.96ms]
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.seda.xyz/home/for-developers/define-your-data-source/accessing-a-public-api.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
