# Create feeds

Source: https://docs.settlemint.com/docs/developers/developer-guides/feeds/create-feeds
Deploy issuer-signed scalar feeds via the factory, create aggregator adapters
for stable consumer addresses, and register external feeds in the directory.




Create a feed when an asset, identity, or global subject needs a registered scalar value source. DALP can deploy an issuer-signed feed, deploy an adapter for an existing feed, or register an external feed address against a subject and topic. This how-to covers the write operations and their request fields. Use [Read feed data](/docs/developers/developer-guides/feeds/read-data) for listing, resolving, and reading feed state. Use [Submit feed updates](/docs/developers/developer-guides/feeds/submit-updates) to publish issuer-signed values after creation.

## Choose the creation path [#choose-the-creation-path]

| Goal                                                                | Use                               | Result                                                                           |
| ------------------------------------------------------------------- | --------------------------------- | -------------------------------------------------------------------------------- |
| Deploy a DALP-managed feed that accepts issuer-signed updates       | Issuer-signed scalar feed factory | A new feed contract registered for the selected subject and topic                |
| Keep a stable consumer address while the underlying feed can change | Aggregator adapter                | An adapter address that resolves the current feed for the same subject and topic |
| Make an existing feed discoverable through DALP                     | External feed registration        | A directory mapping to the existing feed contract                                |

All three paths identify a feed by `subject` plus either `topicName`, `topicId`, or both. When both topic values are present, DALP verifies that they match before submitting the transaction.

## Create an issuer-signed scalar feed [#create-an-issuer-signed-scalar-feed]

Issuer-signed feeds are deployed via the `IssuerSignedScalarFeedFactory` addon. Updates are authorized through EIP-712 typed data signatures from trusted issuers.

### Prerequisites [#prerequisites]

Verify the factory is installed:

```bash
curl "$DALP_API_URL/system/feeds/capabilities" \
  -H "X-Api-Key: $API_KEY"
```

Check that `issuerSignedScalarFeedFactory.installed` is `true` in the response. DALP prepares the shared price topic and issuer-signed scalar feed factory during system and organization deployment. If the capability is not installed yet, finish the platform setup or deployment flow first, then rerun the capabilities check before creating issuer-signed feeds.

The deployment flow is safe to rerun. When the price topic or feed factory already exists, DALP reuses the existing registration instead of creating a duplicate. On a fresh deployment, DALP resolves the new factory from the registry confirmation first. If that receipt-based resolution does not return the factory address, DALP waits for the platform's indexed contract view and resolves the factory there as a fallback. Deterministic configuration or authorization failures fail the setup step; transient network, RPC, or indexing delays are retried by the deployment workflow.

### Register a topic [#register-a-topic]

Before creating a feed, register the topic name in the TopicSchemeRegistry. The API accepts a human-readable `topicName` string, a numeric-string `topicId`, or both. The platform resolves the topic internally when `topicName` is provided. The API verifies the pair when both are provided.

### Deploy the feed [#deploy-the-feed]

```bash
curl -X POST "$DALP_API_URL/api/v2/system/feeds/issuer-signed/create" \
  -H "X-Api-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "subject": "0xTokenAddress",
    "topicName": "PRICE/USD",
    "decimals": 8,
    "description": "USD price feed for token",
    "historyMode": "BOUNDED",
    "historySize": 100,
    "requirePositive": true,
    "driftAllowance": 0
  }'
```

You can also use `topicId` instead of `topicName`:

```bash
curl -X POST "$DALP_API_URL/api/v2/system/feeds/issuer-signed/create" \
  -H "X-Api-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "subject": "0xTokenAddress",
    "topicId": "34863197551733743334059487215836987194269220601176631527793553872548695494516",
    "decimals": 8,
    "description": "USD price feed for token",
    "historyMode": "BOUNDED",
    "historySize": 100,
    "requirePositive": true,
    "driftAllowance": 0
  }'
```

#### Parameters [#parameters]

| Parameter            | Type    | Required                                 | Description                                                                                         |
| -------------------- | ------- | ---------------------------------------- | --------------------------------------------------------------------------------------------------- |
| `subject`            | address | Yes                                      | The asset or entity this feed relates to                                                            |
| `topicName`          | string  | At least one of `topicName` or `topicId` | Human-readable topic name (e.g., "PRICE/USD"). Must be registered in the TopicSchemeRegistry first. |
| `topicId`            | string  | At least one of `topicName` or `topicId` | Numeric string for the registered topic identifier. When paired with `topicName`, it must match.    |
| `decimals`           | number  | Yes                                      | Decimal precision for feed values from 0 to 18                                                      |
| `description`        | string  | Yes                                      | Human-readable description of the feed                                                              |
| `historyMode`        | enum    | Yes                                      | `LATEST_ONLY`, `BOUNDED`, or `FULL`                                                                 |
| `historySize`        | number  | Yes                                      | Ring buffer size when using `BOUNDED` mode (ignored for other modes)                                |
| `requirePositive`    | boolean | Yes                                      | Reject updates with non-positive values                                                             |
| `driftAllowance`     | number  | Yes                                      | Maximum allowed drift in seconds between `observedAt` and block timestamp                           |
| `walletVerification` | object  | No (optional for API key auth)           | Wallet verification for transaction signing: required for session-based auth only                   |

Response (synchronous, default):

```json
{
  "data": {
    "feedAddress": "0x...",
    "subject": "0x...",
    "topicId": "34863197551733743334059487215836987194269220601176631527793553872548695494516",
    "decimals": 8,
    "historyMode": "BOUNDED",
    "transactionHash": "0x..."
  },
  "meta": { "txHashes": ["0x..."] },
  "links": { "self": "/v2/system/feeds/issuer-signed/create" }
}
```

To request asynchronous processing, add `Prefer: respond-async` to the request headers. The server returns HTTP 202 with a status URL for polling:

```json
{
  "transactionId": "01965a1b-...",
  "status": "pending",
  "statusUrl": "/transactions/01965a1b-..."
}
```

Poll the `statusUrl` until `status` changes to `"completed"` or `"failed"`.

The feed is automatically registered in the FeedsDirectory upon creation. DALP indexes the factory creation event and directory registration event together, so the indexed feed includes the subject, topic, decimals, description, history mode, signing domain, issuer registries, and active directory mapping after indexing catches up.

### Create several feeds in one factory transaction [#create-several-feeds-in-one-factory-transaction]

Direct contract integrations can call `batchCreate` on `IssuerSignedScalarFeedFactory`. Use it when all feeds should be created together or none should be created.

`batchCreate` accepts an array of `BatchEntry` values. Each entry uses the same feed fields as the single-feed create call. Encode the contract struct in this order:

1. `subject`
2. `historySize`
3. `decimals`
4. `requirePositive`
5. `topicId`
6. `driftAllowance`
7. `historyMode`
8. `description`

Important behavior:

* The entries array must contain at least one item. An empty array reverts with `EmptyBatch`.
* Entries are processed in input order.
* The call is atomic: if authorization, deployment, or directory registration fails for one entry, the whole transaction reverts.
* The factory emits one `FeedCreated` event per created feed, in the same order as the input entries.
* Authorization is checked for each entry with the same rules as single-feed creation.

The public API create route remains the single-feed interface. Use the contract-level batch call only when your integration is submitting a factory transaction directly.

### Permissions [#permissions]

Feed creation supports two authorization paths:

1. **Feeds Manager role** (system-level): can create feeds for any subject including global (address(0)).
2. **Governance role on subject token**: holders of the GOVERNANCE role on a specific DALP token can create feeds for that token, provided the token supports the ISMART and ISMARTTokenAccessManaged interfaces. Does not apply to global feeds.

If neither condition is met, the factory reverts with `UnauthorizedFeedCreation`.

| Error                      | Cause                                                                                                                                                  |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `UnauthorizedFeedCreation` | Caller lacks FEEDS\_MANAGER\_ROLE and does not hold GOVERNANCE\_ROLE on the subject token (or subject is address(0) and caller is not a feeds manager) |

## Create an aggregator adapter [#create-an-aggregator-adapter]

Adapters are stable-address proxies that resolve to the current underlying feed for a `(subject, topic)` pair. Consumers point at the adapter address instead of the feed directly. When you replace the underlying feed, the adapter automatically resolves to the new feed without consumers changing their configuration.

### Prerequisites [#prerequisites-1]

Verify the adapter factory is installed:

```bash
curl "$DALP_API_URL/system/feeds/capabilities" \
  -H "X-Api-Key: $API_KEY"
```

Check that `scalarFeedAggregatorAdapterFactory.installed` is `true`.

### Deploy the adapter [#deploy-the-adapter]

```bash
curl -X POST "$DALP_API_URL/api/v2/system/feeds/adapters/create" \
  -H "X-Api-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "subject": "0xTokenAddress",
    "topicName": "PRICE/USD"
  }'
```

| Parameter            | Type    | Required                                 | Description                                                                       |
| -------------------- | ------- | ---------------------------------------- | --------------------------------------------------------------------------------- |
| `subject`            | address | Yes                                      | The asset or entity                                                               |
| `topicName`          | string  | At least one of `topicName` or `topicId` | Human-readable topic name                                                         |
| `topicId`            | string  | At least one of `topicName` or `topicId` | Numeric string for the topic identifier                                           |
| `walletVerification` | object  | No (optional for API key auth)           | Wallet verification for transaction signing: required for session-based auth only |

Response (synchronous, default):

```json
{
  "data": {
    "adapterAddress": "0x...",
    "subject": "0x...",
    "topicId": "34863197551733743334059487215836987194269220601176631527793553872548695494516",
    "transactionHash": "0x..."
  },
  "meta": { "txHashes": ["0x..."] },
  "links": { "self": "/v2/system/feeds/adapters/create" }
}
```

Add `Prefer: respond-async` for asynchronous processing (HTTP 202 with `statusUrl` for polling).

### Permissions [#permissions-1]

Adapter creation follows the same two-path authorization as feed creation:

1. **Feeds Manager role** (system-level): can create adapters for any subject including global (address(0)).
2. **Governance role on subject token**: can create adapters for their specific token. Does not apply to global subjects.

| Error                      | Cause                                                                                     |
| -------------------------- | ----------------------------------------------------------------------------------------- |
| `UnauthorizedFeedCreation` | Caller lacks FEEDS\_MANAGER\_ROLE and does not hold GOVERNANCE\_ROLE on the subject token |

## Register an external feed [#register-an-external-feed]

Register an existing feed contract, such as a Chainlink-compatible price feed, in the directory. The registered feed becomes discoverable through the same `(subject, topic)` lookup as platform-managed feeds. DALP stores the directory mapping and read metadata for external feeds. The external provider still owns update permissions, source controls, monitoring, and service levels.

```bash
curl -X POST "$DALP_API_URL/api/v2/system/feeds/register-external" \
  -H "X-Api-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "subject": "0xTokenAddress",
    "topicName": "PRICE/USD",
    "feedAddress": "0xExternalFeedContract",
    "kind": "SCALAR",
    "description": "Chainlink-compatible USD price feed for this token"
  }'
```

External feed registration writes a directory mapping. It does not deploy the feed, update the external contract, or monitor the external provider. Before registering the address, verify the contract exposes the feed shape your consumer expects. Also verify the selected topic describes the value the feed returns.

| Parameter            | Type    | Required                                 | Description                                                                       |
| -------------------- | ------- | ---------------------------------------- | --------------------------------------------------------------------------------- |
| `subject`            | address | Yes                                      | The asset or entity                                                               |
| `topicName`          | string  | At least one of `topicName` or `topicId` | Human-readable topic name                                                         |
| `topicId`            | string  | At least one of `topicName` or `topicId` | Numeric string for the topic identifier                                           |
| `feedAddress`        | address | Yes                                      | The external feed contract address                                                |
| `kind`               | enum    | Yes                                      | Feed kind (`SCALAR`)                                                              |
| `description`        | string  | Yes                                      | Human-readable feed description; empty values are rejected                        |
| `walletVerification` | object  | No (optional for API key auth)           | Wallet verification for transaction signing: required for session-based auth only |

Response (synchronous, default):

```json
{
  "data": {
    "subject": "0xTokenAddress",
    "topicId": "34863197551733743334059487215836987194269220601176631527793553872548695494516",
    "feedAddress": "0xExternalFeedContract",
    "kind": "SCALAR",
    "transactionHash": "0x..."
  },
  "meta": { "txHashes": ["0x..."] },
  "links": { "self": "/v2/system/feeds/register-external" }
}
```

Add `Prefer: respond-async` for asynchronous processing. The server queues the `registerFeed` transaction and returns a status URL for polling.

## Directory operations [#directory-operations]

### Resolve a feed [#resolve-a-feed]

Look up the feed registered for a `(subject, topic)` pair. You can use either `topicName` or `topicId`:

```bash
curl "$DALP_API_URL/system/feeds/resolve?subject=0xToken&topicName=PRICE/USD" \
  -H "X-Api-Key: $API_KEY"
```

Or with `topicId`:

```bash
curl "$DALP_API_URL/system/feeds/resolve?subject=0xToken&topicId=34863197551733743334059487215836987194269220601176631527793553872548695494516" \
  -H "X-Api-Key: $API_KEY"
```

Returns the feed address, kind, schema hash, adapter address (if one exists), and indexed data from DIDX.

### Replace a feed [#replace-a-feed]

Swap the feed registered for a `(subject, topic)` pair with a different feed contract:

```bash
curl -X PUT "$DALP_API_URL/system/feeds/replace" \
  -H "X-Api-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "subject": "0xTokenAddress",
    "topicName": "PRICE/USD",
    "newFeedAddress": "0xNewFeedContract",
    "kind": "SCALAR",
    "description": "Chainlink-compatible USD price feed for this token"
  }'
```

| Parameter            | Type    | Required                                 | Description                                                                       |
| -------------------- | ------- | ---------------------------------------- | --------------------------------------------------------------------------------- |
| `subject`            | address | Yes                                      | The asset or entity                                                               |
| `topicName`          | string  | At least one of `topicName` or `topicId` | Human-readable topic name                                                         |
| `topicId`            | string  | At least one of `topicName` or `topicId` | Numeric string for the topic identifier                                           |
| `newFeedAddress`     | address | Yes                                      | The new feed contract address                                                     |
| `kind`               | enum    | Yes                                      | Feed kind (`SCALAR`)                                                              |
| `description`        | string  | Yes                                      | Human-readable feed description; empty values are rejected                        |
| `walletVerification` | object  | No (optional for API key auth)           | Wallet verification for transaction signing: required for session-based auth only |

If an aggregator adapter exists for this `(subject, topic)`, the adapter resolves to the new feed. Replacement keeps the subject, topic, and adapter address stable. DALP clears the indexed latest answer until the new feed emits its next update. Use replacement when only the registered feed address changes. The replacement feed must use the same kind, schema hash, and decimals as the previous feed. DALP rejects mismatches with `KindMismatch`, `SchemaHashMismatch`, or `DecimalMismatch`. Keep the value semantics and description aligned with the previous mapping so consumers do not reinterpret the adapter output.

### Remove a feed [#remove-a-feed]

Remove a feed registration from the directory. Removal deactivates the mapping for this subject and topic. Consumers that resolve through the directory no longer get an active feed for the pair. DALP clears cached token price data when the removed mapping was used as a price feed.

```bash
curl -X DELETE "$DALP_API_URL/system/feeds/remove" \
  -H "X-Api-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "subject": "0xTokenAddress",
    "topicName": "PRICE/USD"
  }'
```

| Parameter            | Type    | Required                                 | Description                                                                       |
| -------------------- | ------- | ---------------------------------------- | --------------------------------------------------------------------------------- |
| `subject`            | address | Yes                                      | The asset or entity                                                               |
| `topicName`          | string  | At least one of `topicName` or `topicId` | Human-readable topic name                                                         |
| `topicId`            | string  | At least one of `topicName` or `topicId` | Numeric string for the topic identifier                                           |
| `walletVerification` | object  | No (optional for API key auth)           | Wallet verification for transaction signing: required for session-based auth only |

<Mermaid
  chart="`
flowchart TB
  Factory(Feed Factory) -->|creates| Feed(Feed Contract)
  Feed -->|registered in| Directory(FeedsDirectory)
  Directory -->|resolved by| Adapter(Aggregator Adapter)
  Adapter -->|consumed by| Consumer(Consumer Contract)

  External(External Feed) -->|registered in| Directory

  style Factory fill:#5fc9bf,stroke:#3a9d96,stroke-width:2px,color:#fff
  style Feed fill:#6ba4d4,stroke:#4a7ba8,stroke-width:2px,color:#fff
  style Directory fill:#8571d9,stroke:#654bad,stroke-width:2px,color:#fff
  style Adapter fill:#b661d9,stroke:#8a3fb3,stroke-width:2px,color:#fff
  style Consumer fill:#5fc9bf,stroke:#3a9d96,stroke-width:2px,color:#fff
  style External fill:#6ba4d4,stroke:#4a7ba8,stroke-width:2px,color:#fff

`"
/>

## Operational notes [#operational-notes]

* External registration and replacement require a non-empty `description`. Use the description to preserve feed semantics for auditors and downstream readers.
* `kind` currently accepts `SCALAR`. Do not pass other feed kinds unless your route schema exposes them.
* Mutation responses include `transactionHash`. Store it with the system actor and request ID. Operations teams can use those records to reconcile the API write with chain activity.
* Feed creation and directory writes do not prove that a value is fresh. Read the feed after creation or replacement and inspect the indexed `latestValue` fields before relying on the feed in a production workflow.

## Related [#related]

* [Data feeds overview](/docs/developers/developer-guides/feeds/overview)
* [Read feed data](/docs/developers/developer-guides/feeds/read-data)
* [Submit feed updates](/docs/developers/developer-guides/feeds/submit-updates)
