AR.IO LogoAR.IO Documentation

Content Moderation

Overview

Arweave is a network designed for permanent storage of data. It is a practical impossibility for data to be wholly removed from the network once it has been uploaded.

The AR.IO Network has adopted Arweave's voluntary content moderation model, whereby every participant of the network has the autonomy to decide which content they want to (or can legally) store, serve, and see. Each gateway operating on the network has the right and ability to blocklist any content, ArNS name, or address that is deemed in violation of its content policies or is non-compliant with local regulations.

Gateway operators may set content to be blocked by their gateway by submitting a PUT request to their gateway defining the content to be blocked. This requires that the ADMIN_API_KEY environmental variable to be set in order to authenticate the moderation request.

The simplest method for submitting moderation requests to a gateway is to use curl in a terminal.

Quick Start

Set Up Admin API Key

Configure your admin API key in your .env file:

# Set a secure admin API key
ADMIN_API_KEY=your_secure_admin_key_here

Security

Choose a strong, unique admin API key. This key provides administrative access to your gateway and should be kept secure.

Test API Access

Verify your admin API key is working:

# Test admin endpoint access
curl -H "Authorization: Bearer your_secure_admin_key_here" \
  http://localhost:3000/ar-io/admin/debug

Block Your First Content

Block a specific transaction ID:

curl -X 'PUT' \
  'http://localhost:3000/ar-io/admin/block-data' \
  -H 'accept: */*' \
  -H 'Authorization: Bearer your_secure_admin_key_here' \
  -H 'Content-Type: application/json' \
  -d '{
  "id": "3lyxgbgEvqNSvJrTX2J7CfRychUD5KClFhhVLyTPNCQ",
  "notes": "Content violates our policies",
  "source": "Manual Review"
}'

Authentication

Moderation requests must contain the gateway's ADMIN_API_KEY in the request Header, as Authorization: Bearer.

For example, if a gateway's ADMIN_API_KEY is set to secret, any request must contain Authorization: Bearer secret in the Header.

Block Data

Specific data items can be blocked by a gateway operator by submitting a PUT request containing a json object with three keys:

  • id: The Arweave transaction Id of the data item to be blocked.
  • notes: Any note the gateway operator wants to leave him/herself as to the reason the content is blocked.
  • source: A note as to where the content was identified as requiring moderation. i.e. a public block list.

Requests to block data must be submitted to the gateway's /ar-io/admin/block-data endpoint.

curl -X 'PUT' \
  'http://localhost:3000/ar-io/admin/block-data' \
  -H 'accept: */*' \
  -H 'Authorization: Bearer secret' \
  -H 'Content-Type: application/json' \
  -d '{
  "id": "3lyxgbgEvqNSvJrTX2J7CfRychUD5KClFhhVLyTPNCQ",
  "notes": "This content is offensive",
  "source": "Public Block list"
}'

Unblock Data

At this time, blocked data items can only be unblocked by manually deleting the corresponding row from the data/sqlite/moderation.db database. The Arweave transaction Id of the blocked data item is stored in the database as raw bytes, which sqlite3 accepts as a BLOB (Binary Large OBject), and so cannot be accessed easily using the original transaction Id, which is a base64url. Sqlite3 is able to interact with a hexadecimal representation of the BLOB, by using a BLOB literal. To do so, wrap a hexadecimal representation of the Arweave transaction Id in single quotes, and prepend an X i.e. X'de5cb181b804bea352bc9ad35f627b09f472721503e4a0a51618552f24cf3424'.

Where possible, consider using the notes or source values to identify rows for deletion rather than the id.

sqlite3 data/sqlite/moderation.db "DELETE FROM blocked_ids WHERE id=X'de5cb181b804bea352bc9ad35f627b09f472721503e4a0a51618552f24cf3424';"
# Note that the id in this command is a BLOB literal using the hexadecimal representation of the Arweave transaction Id, not the transaction Id in its normal base64url format
sqlite3 data/sqlite/moderation.db "DELETE FROM blocked_ids WHERE block_source_id = (SELECT id FROM block_sources WHERE name='Public Block List');"
# This command uses a subquery to look up the id in block_sources where name='Public Block List'
# This command will unblock ALL data items marked with this source value

Block ArNS Name

ArNS names can be blocked so that a gateway will refuse to serve their associated content even if the name holder updates the Arweave transaction Id that the name points at.

This is done via an authenticated PUT request to the endpoint /ar-io/admin/block-name containing a json object with three keys:

  • name: The ArNS name to be blocked.
  • notes: Any note the gateway operator wants to leave him/herself as to the reason the content is blocked.
  • source: A note as to where the content was identified as requiring moderation. i.e. a public block list.
curl -X 'PUT' \
  'http://localhost:3000/ar-io/admin/block-name' \
  -H 'accept: */*' \
  -H 'Authorization: Bearer secret' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "i-bought-a-potato",
  "notes": "Potatoes are offensive",
  "source": "Public Block list"
}'

Undernames

For moderation purposes, each undername of an ArNS name is treated as a separate name and must be moderated separately.

Unblock ArNS Name

Gateway operators can unblock ArNS names that were previously blocked.

This is done via an authenticated PUT request to the endpoint /ar-io/admin/unblock-name containing a json object with a single key:

  • name: The ArNS name to be unblocked
curl -X 'PUT' \
  'http://localhost:3000/ar-io/admin/unblock-name' \
  -H 'accept: */*' \
  -H 'Authorization: Bearer secret' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "i-bought-a-potato",
}'

How is this guide?