DEVELOPER DOCS
GraphQL

Querying with GraphQL

Transaction metadata can be queried using GraphQL. This includes both metadata automatically stored for each transaction and custom metadata you design yourself using our tags feature.

ℹ️

If you prefer learning by building a project, you may enjoy this step-by-step tutorial where you’ll learn how to setup a project, install the Apollo GraphQL libraries and then build a tool to search Arweave for recently uploaded image files.

Bundlr vs Arweave GraphQL

Bundlr GraphQL and Arweave GraphQL (opens in a new tab) both offer ways to query transaction metadata, however, they differ in several ways. Bundlr GraphQL requires you to connect to the node-specific endpoint where you posted your transaction, while Arweave GraphQL uses a universal endpoint for all queries. Bundlr GraphQL is cross-chain, it includes the address (regardless of chain) that posted the transaction, while Arweave GraphQL only includes Arweave addresses. Bundlr GraphQL also includes the currency used for payment, a receipt (if requested when uploading), and a true timestamp accurate to the millisecond of when the transaction was posted. Arweave GraphQL allows for querying by block structure (opens in a new tab), including block ID, block range, and block height, which Bundlr GraphQL does not support.

Bundlr GraphQLArweave GraphQL
EndpointNode-specefic. Connect to the endpoint associated with the node where you posted your transaction.Universal endpoint for all queries.
Cross-chainYes. Includes the address (regardless of chain) that posted the transaction.No. Includes Arweave addresses only.
Original payment currencyIncluded.Not included.
TimestampIncludes a timestamp accurate to the millisecond of when the transaction was posted, along with an (optional) cryptographically signed receipt.Timestamp is based on block time, accurate to ~2 minutes.
BlocksNot included.Included (opens in a new tab). You can query by block ID, block range, and block height.

GraphQL clients

You can query using an HTTP library like fetch or axios. You can also use specialized clients like Apollo Client (opens in a new tab) or urql (opens in a new tab).

The next two sections detail first Bundlr GraphQL followed by Arweave GraphQL. While the two schemas are similar, there are differences you’ll need to be aware of when developing your projects. There is no one schema that is “better” than the other, the decision on which to use will depend on your own project and your specific needs.

Bundlr GraphQL

Anatomy of a query

A GraphQL query is made up of:

  • Query Arguments: Arguments that specify search parameters, limit the number of results returned, or enable pagination.
  • Results Fields: Fields that define the data you want to retrieve.

Query arguments

Any of the following query arguments can be used as search parameters:

FieldDescription
idsAn array of transaction IDs passed as strings. Values are ORed together, matching results will include transactions that have any of the supplied IDs.
ownerThe address used when posting the transaction. Can be a native address from any of the chains supported by Bundlr. Note in results fields, this is referred to as address.
currencyThe currency used to pay for the transaction.
tagsAn array of tag name / value pairs passed as JSON objects.

Results fields

When building a query, any of the following values be included in your results:

FieldDescription
idThe transaction ID.
addressThe address used when posting the transaction. Can be a native address from any of the chains supported by Bundlr. Note in query arguements, this is referred to as owner.
currencyThe currency used to pay for the transaction.
receipt {
  deadlineHeight
  signature
  version
}
An optional receipt, only exists if a user requested one at upload.
deadlineHeight: The block number by which the transaction must be finalized on Arweave.
signature: A signed deep hash of the JSON receipt.
tags {
  name
  value
}
An array of tags supplied as name / value pairs. Exists if the user added them at upload.
timestampThe timestamp, accurate to the millisecond of when the transaction was posted. In cases where there exists a receipt, this value will be the same as the receipt timestamp.

Endpoints

Connect to the GraphQL endpoint associated with the node you uploaded your transaction to.

NodeEndpoint
Node 1https://node1.bundlr.network/graphql (opens in a new tab)
Node 2https://node2.bundlr.network/graphql (opens in a new tab)
Devnethttps://devnet.bundlr.network/graphql (opens in a new tab)

GraphQL sandbox

Clicking on any of the endpoint URLs above will direct you to the GraphQL Sandbox used for building and testing queries. Press Control+Space at any time to see an interactive popup window of either query arguments or results fields.

Sample queries

Queries return transaction metadata. To then retrieve data, use the returned transaction ID and download the data from a gateway using an URL formed as follows https://arweave.net/[transaction-id].

Transaction IDs

Search by transaction IDs.

query getByIds {
  transactions(
    ids: ["--52WQHJIJod_rni8pkl1Vxt9MFGoXZAm8SC7ex6C1o", "--52THRWpX_RJzGcNXmtQ2DSP37d1e1VQ4YmvbY5ZXo"]) {
    edges {
      node {
        id
        tags {
          name
          value
        }
      }
    }
  }
}

Timestamps

Search by timestamps.

query getByTimestamp {
  transactions(timestamp: { from: 1688144401000, to: 1688317201000 }) {
    edges {
      node {
        id
      }
    }
  }
}
ℹ️

Bundlr timestamps are accurate to the millisecond, so you need to provide a timestamp in millisecond format. You can convert from human-readable time to UNIX timestamp using websites like Epoch101 (opens in a new tab), be sure to convert in millisecond format not second.

Owners

Search for transactions matching the wallet address used when posting the transaction.

query getByOwner {
  transactions(
    owners: ["0xBcb812C6e26F4F0F78Bd7B6222461FF24F2942AE", "0xaC568a981B1370B2e1bAA8cE30BD5AC9E28C572D"]) {
    edges {
      node {
        id
        address
      }
    }
  }
}
 

Tags

Search for transactions matching tag name / value pairs.

query getAllPNGs {
  transactions(tags: [{ name: "Content-Type", values: ["image/png"] }]) {
    edges {
      node {
        id
        address
      }
    }
  }
}

Search for transactions matching the tag with name Content-Type and the values of image/png OR image/jpg.

query getTagsWithOR {
  transactions(tags: [{ name: "Content-Type", values: ["image/png", "image/jpg"] }]) {
    edges {
      node {
        tags {
          name
          value
        }
      }
    }
  }
}
 

Search for transactions matching the tag with name Content-Type and the values of image/png AND image/jpg.

query getTagsWithAnd {
  transactions(
    tags: [
      { name: "Content-Type", values: ["image/jpg"] }
      { name: "Content-Type", values: ["image/png"] }
    ]
  ) {
    edges {
      node {
        tags {
          name
          value
        }
      }
    }
  }
}

Limiting results

Limit the number of results returned by including the limit parameter.

query getAllPNGs {
  transactions(
    limit: 10
    tags: [{ name: "Content-Type", values: ["image/png"] }]
  ) {
    edges {
      node {
        id
        address
      }
    }
  }
}

Pagination

You can request a maximum of 100 results returned from each query, to obtain additional results use pagination.

When using pagination you:

  1. Retrieve the cursor field, this acts like a bookmark in the search results you can then return to.
  2. Use saved cursor value to obtain subsequent search results.

The following query returns 10 transactions tagged image/png occurring after the cursor with value: LS02d1NsM3R6aUprd3dKUzVjN1FXaWg5aUxsbXh5dVJJbGlydHJtNlpPbw. To then obtain the next 10 transactions, use the final cursor value returned from this query as the value of the after parameter in the following query.

query getPNGs {
  transactions(
    limit: 10
    tags: [{ name: "Content-Type", values: ["image/png"] }]
    after: "LS02d1NsM3R6aUprd3dKUzVjN1FXaWg5aUxsbXh5dVJJbGlydHJtNlpPbw"
  ) {
    edges {
      node {
        id
      }
      cursor
    }
  }
}

Sorting

You can sort results by timestamp in either ascending or descending order using the order field.

query getAllByOwnerAsc {
  transactions(
    owners: ["0xBcb812C6e26F4F0F78Bd7B6222461FF24F2942AE"]
    order: ASC
  ) {
    edges {
      node {
        id
        address
      }
    }
  }
}
query getAllByOwnerDesc {
  transactions(
    owners: ["0xBcb812C6e26F4F0F78Bd7B6222461FF24F2942AE"]
    order: DESC
  ) {
    edges {
      node {
        id
        address
      }
    }
  }
}

Arweave GraphQL

Anatomy of a query

A GraphQL query is made up of:

  • Query Arguments: Arguments that specify search parameters, limit the number of results returned, or enable pagination.
  • Results Fields: Fields that define the data you want to retrieve.

Query arguments

Any of the following query arguments can be used as search parameters:

FieldDescription
idsAn array of transaction IDs passed as strings. Values are ORed together, matching results will include transactions that have any of the supplied IDs.
ownerThe Arweave address used when posting the transaction. Note if you post to Bundlr using a non-Arweave wallet address, it will be converted into an Arweave-like address and stored in this field. There is no way to retrieve eth or sol addresses from Arweave GraphQL, you must use Bundlr GraphQL.
recipientsThe currency used to pay for the transaction.
bundledInTransaction ID of the parent bundle for this transaction. Transaction ID can be of a nested bundle or a regular bundle.
blockDetails specific to a transaction's block.
tagsAn array of tag name / value pairs passed as JSON objects. Values are ORed together, matching results will include transactions matching any of the supplied tags.

Results fields

When building a query, you can request any of the following values be included in your results:

FieldDescription
idThe transaction ID.
anchorA value used to prevent against double spends.
signatureThe signature used to sign the transaction.
recipientAddress of the account the tx was sent to (use for fund transfers).
ownerThe Arweave address used when posting the transaction. Note if you post to Bundlr using a non-Arweave wallet address, it will be converted into an Arweave-like address and stored in this field. There is no way to retrieve eth or sol addresses from Arweave GraphQL, you must use Bundlr GraphQL.
fee {
  winston
  ar
}
The transaction mining fee.
quantity {
  winston
  ar
}
The amount paid for the transaction.
data {
  size
  type
}
The size and type of the data payload.
tagsAn array of tags supplied as name / value pairs. Exists if the user added them at upload.
block {
  id
  timestamp
  height
  previous
}
Details specific to a transaction's block, including block number, mining date, block hash, and the previous block hash.
bundledInTransaction ID of the parent bundle for this transaction. Transaction ID can be of a nested bundle or a regular bundle.

Endpoints

Arweave offers a universal endpoint, you do not need to pick an endpoint associated with the node you uploaded to. The three endpoints below all provide access to the same dataset, use the one with the fastest response times.

GraphQL playground

Clicking on any of the endpoint URLs will direct you to the GraphQL Playground used for building and testing queries. Press Control+Space at any time to see an interactive popup window of either query arguments or results fields.

Sample queries

Queries return transaction metadata. To then retrieve data, use the returned transaction ID and download the data from a gateway using an URL formed as follows https://arweave.net/[transaction-id].

Transaction IDs

Search by transaction IDs.

query getByIds {
  transactions(ids: ["1t-Z0oDxQLvACpLXUwwfbplw7vHialWH8mkNAvzTkDw", "1w6PBHQ5e0hMJWsfRCJr66JvQAcyws0k4D97kG4GVm8"]) {
    edges {
      node {
        id
        tags {
          name
          value
        }
      }
    }
  }
}

Owners

Search for transactions matching the Arweave wallet address used when posting the transaction.

query getByOwners {
  transactions(owners: ["M6w588ZkR8SVFdPkNXdBy4sqbMN0Y3F8ZJUWm2WCm8M"]) {
    edges {
      node {
        id
      }
    }
  }
}

Tags

Search for transactions matching tag name / value pairs.

query getAllPNGs {
  transactions(tags: { name: "Content-Type", values: ["image/png"] }) {
    edges {
      node {
        id
      }
    }
  }
}

Limiting results

Limit the number of results returned by including the first parameter.

query get10Pngs {
  transactions(
    first: 10
    tags: { name: "Content-Type", values: ["image/png"] }
  ) {
    edges {
      node {
        id
      }
    }
  }
}

Pagination

You can request a maximum of 100 results returned from each query, to obtain additional results use pagination.

When using pagination you must:

  1. Retrieve the cursor field, this acts like a bookmark in the search results you can then return to.
  2. Use saved cursor values to obtain subsequent search results.

The following query returns 10 transactions tagged image/png occurring after the cursor with value LS02d1NsM3R6aUprd3dKUzVjN1FXaWg5aUxsbXh5dVJJbGlydHJtNlpPbw. To then obtain the next 10 transactions, use the final cursor value returned from this query as the value of the after parameter in the following query.

query getPNGs {
  transactions(
    first: 10
    tags: [{ name: "Content-Type", values: ["image/png"] }]
    after: "LS02d1NsM3R6aUprd3dKUzVjN1FXaWg5aUxsbXh5dVJJbGlydHJtNlpPbw"
  ) {
    edges {
      node {
        id
      }
      cursor
    }
  }
}

Sorting

You can sort results by block height in either ascending or descending order using the sort parameter.

query getByOwnersAsc {
  transactions(
    owners: ["M6w588ZkR8SVFdPkNXdBy4sqbMN0Y3F8ZJUWm2WCm8M"]
    sort: HEIGHT_ASC
  ) {
    edges {
      node {
        id
      }
    }
  }
}
query getByOwnersDesc {
  transactions(
    owners: ["M6w588ZkR8SVFdPkNXdBy4sqbMN0Y3F8ZJUWm2WCm8M"]
    sort: HEIGHT_DESC
  ) {
    edges {
      node {
        id
      }
    }
  }
}

Further reading

Additional information on Arweave GraphQL can be found on their website (opens in a new tab).