# RPC API \[Newton Gateway JSON-RPC API reference for policy-based transaction authorization]

The Newton Gateway provides a JSON-RPC 2.0 interface for submitting policy evaluation tasks to the Newton Protocol AVS (Actively Validated Service). The protocol evaluates user intents against Rego policies and returns cryptographic proofs of compliance through BLS signatures.

For client-side helpers that wrap these RPC calls, see the [SDK Reference](/developers/reference/sdk-reference). For a step-by-step walkthrough of building on Newton, see the [Integration Guide](/developers/guides/integration-guide).

## API version scope

Policy-set request schemas below apply to the current gateway API. Use an SDK release that supports task submission and `simulatePolicy`.

## Base URLs

| Network | Environment | URL |
|---------|-------------|-----|
| Testnet (Sepolia) | Production | `https://gateway.testnet.newton.xyz/rpc` |
| Testnet (Sepolia) | Staging | `https://gateway.stagef.testnet.newton.xyz/rpc` |
| Mainnet | Production | `https://gateway.newton.xyz/rpc` |
| Mainnet | Staging | `https://gateway.stagef.newton.xyz/rpc` |

**Protocol:** JSON-RPC 2.0 over HTTPS

:::note
Gateway JSON-RPC requests must be sent to the `/rpc` endpoint. Requests to the host root, such as `https://gateway.testnet.newton.xyz`, return a 404 response instead of a JSON-RPC response.
:::

Use a UUID string for the JSON-RPC `id` field. Numeric IDs are valid in the JSON-RPC 2.0 specification, but the Newton Gateway expects request IDs as strings.

:::code-group
```json [Request Format]
{
  "jsonrpc": "2.0",
  "method": "<method_name>",
  "params": { ... },
  "id": "7ca6621b-7aa4-4bb7-a896-1f2b58a18c78"
}
```

```json [Success Response]
{
  "jsonrpc": "2.0",
  "result": { ... },
  "id": "<request_id>"
}
```

```json [Error Response]
{
  "jsonrpc": "2.0",
  "error": {
    "code": -32600,
    "message": "Invalid request"
  },
  "id": "<request_id>"
}
```
:::

***

## Authentication

:::info
All API requests require authentication via API key. Include the key in the `Authorization` header:

```
Authorization: Bearer <your_api_key>
```

API keys are issued with specific permissions. See [Getting an API Key](/developers/overview/dashboard-api-keys) to get yours.
:::

### Permission Levels

| Permission | Description |
|------------|---------------------------------------------------|
| `RpcRead` | Read-only operations: task submission, simulation |
| `RpcWrite` | Write operations: secrets management |

### Example

```bash
curl -X POST https://gateway.testnet.newton.xyz/rpc \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your_api_key_here" \
  -d '{"jsonrpc":"2.0","method":"newt_createTask","params":{...},"id":"7ca6621b-7aa4-4bb7-a896-1f2b58a18c78"}'
```

### Policy Client Ownership

Some endpoints require **ownership verification** of a `policy_client` address. This mechanism protects access to stored secrets and ensures only authorized users can manage secrets for a given PolicyClient.

:::note
As of v0.2.0, ownership is determined **on-chain** via the `INewtonPolicyClient.getOwner()` method on the PolicyClient contract. PolicyClient ownership transfers through `setPolicyClientOwner()` on the contract. The Gateway reads on-chain state for every ownership check.
:::

**How Ownership Works:**

1. **Ownership is read from the chain** — the Gateway calls `getOwner()` on the `policy_client` contract to determine the current owner.
2. **Ownership is verified** when calling endpoints that require it. The Gateway checks that the caller's API key is associated with the on-chain owner of the `policy_client`.
3. **Ownership is transferable** — call `setPolicyClientOwner()` as the current owner; the Gateway reads the new on-chain owner on its next check.

**Endpoints Requiring Ownership Verification:**

| Endpoint | Ownership Required |
|-----|-----|
| `newt_simulatePolicyData` | No (caller provides secrets directly) |
| `newt_simulatePolicyDataWithClient` | Yes (fetches stored secrets) |
| `newt_simulatePolicy` | Yes; explicitly authorized read-only admin keys can bypass |
| `newt_storeEncryptedSecrets` | Yes (verifies on-chain owner) |

:::note
The pinned `newt_simulatePolicy` handler checks client ownership for every set, including pure-Rego sets. An explicitly authorized admin API key can bypass this check on read endpoints only, after its permission is revalidated.
:::

**Error Responses:**

If ownership verification fails, you will receive one of these errors:

* `"policy_client is owned by another user"` -- The `policy_client` is owned by a different address on-chain.
* `"policy client has no owner"` -- The contract returned a zero address for `getOwner()`.

***

## Conventions

### Hex Value Encoding

Following Ethereum JSON-RPC conventions:

**Quantities (integers, numbers):**

* Encode as hex with `0x` prefix
* Use most compact representation (no leading zeros except for zero itself)
* Zero is represented as `"0x0"`

```
0x41      (65 in decimal)
0x400     (1024 in decimal)
0x0       (zero)
```

**Unformatted Data (byte arrays, addresses, hashes):**

* Encode as hex with `0x` prefix
* Two hex digits per byte
* Even number of digits required

```
0x1234567890123456789012345678901234567890   (20-byte address)
0x28dca9f7                                   (4-byte function selector)
0x                                           (empty data)
```

### WASM Arguments

Task submission and policy-set simulation use an ordered array with one hex-encoded entry per policy. Preserve repeated policies and their positions. For two pure-Rego policies use `["0x", "0x"]`, not a scalar or an empty array.

| Method | Argument shape and meaning |
|---|---|
| SDK task methods and `simulatePolicy` | `wasmArgs: Hex[]`; SDK removes the `0x` prefix from each entry on the wire |
| `newt_createTask` / `newt_sendTask` | `wasm_args: string[]`; input to each policy's optional WASM |
| `newt_simulatePolicy` | `wasm_args: string[]`; input to each policy's optional WASM |
| `newt_simulateTask` | `wasm_args: string[]`; **precomputed oracle outputs**, not WASM execution inputs |
| `newt_simulatePolicyData` / `newt_simulatePolicyDataWithClient` | Scalar `wasm_args`; input to one policy's WASM |

Encode JSON inputs with `stringToHex(JSON.stringify(input))` from viem. Use the canonical `0x` prefix in raw requests. An empty `0x` entry represents no data for a pure-Rego policy.

### Address Format

Ethereum addresses are 20-byte hex strings with `0x` prefix:

```
0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
```

Addresses are case-insensitive but checksummed addresses are recommended.

***

## Common Types

### TaskIntent

Represents a transaction intent to be evaluated against a policy.

| Field | Type | Required | Description |
|---|---|---|---|
| `from` | `Address` | Yes | Transaction sender address |
| `to` | `Address` | Yes | Transaction recipient address |
| `value` | `Quantity` | Yes | Wei value to transfer (hex encoded) |
| `data` | `Data` | Yes | Transaction calldata (hex encoded) |
| `chain_id` | `Quantity` | Yes | Target chain ID (hex encoded) |
| `function_signature` | `Data` | Yes | Hex-encoded human-readable ABI signature used for calldata decoding, or `"0x"` when the intent has no calldata |

:::details[TaskIntent Example]
```json
{
  "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
  "to": "0xb1aD5f82407bC0f19f42b2614fb9083035a36b69",
  "value": "0x0",
  "data": "0xa9059cbb000000000000000000000000e42e3458283032c669c98e0d8f883a92fc64fe220000000000000000000000000000000000000000000000000000000000000001",
  "chain_id": "0xaa36a7",
  "function_signature": "0x62757928616464726573732c75696e743235362c75696e74333229"
}
```
:::

#### Function signature examples

`function_signature` is not the 4-byte selector. For contract calls, hex-encode the human-readable ABI signature without the `function ` prefix, for example `transfer(address,uint256)`. For native ETH transfers or any intent with no calldata, set both `data` and `function_signature` to `"0x"`.

| Intent kind | `data` | `function_signature` |
|---|---|---|
| Native ETH transfer | `"0x"` | `"0x"` |
| Contract call | ABI-encoded calldata | Hex-encoded signature, for example `transfer(address,uint256)` |

### Policy-set snapshot

A Task contains `policyId`, `policyRevision`, and an ordered `policies` array frozen at admission. Each entry is `{ policy, config: { policyParams, expireAfter } }`. `wasmArgs[i]` belongs to `policies[i]`.

The response's `policy_task_data[i]` retains the same position and carries `policyId`, `policyAddress`, resolved `policy` bytes, and `policyData` evidence entries (`wasmArgs`, `data`, `expireBlock`). The response has one aggregate `allowed` boolean. Do not expect an individual verdict on each evidence entry; use simulation's `policies[i].allowed` for per-policy diagnostics. Never reorder, flatten, or deduplicate signed evidence.

### TaskStatus

Enumeration of task processing states.

| Value | Description |
|---|---|
| `pending` | Task queued for processing |
| `processing` | Task being evaluated by operators |
| `success` | Task completed successfully |
| `failed` | Task evaluation failed |
| `timeout` | Task exceeded timeout threshold |

***

## RPC Methods

### newt\_createTask

Creates a task and waits synchronously for the BLS aggregation result. Use this for simple integrations where blocking is acceptable.

**Permission:** `RpcRead`

#### Parameters

| Field | Type | Required | Description |
|---|---|---|---|
| `policy_client` | `Address` | Yes | Policy client contract address |
| `intent` | `TaskIntent` | Yes | Transaction intent to evaluate |
| `intent_signature` | `Data` | No | Hex-encoded EIP-712 signature of the exact intent. Optional in the base schema, but required by policies and identity flows that consume `input.intent_signature` |
| `quorum_number` | `Data` | No | Quorum numbers (hex bytes, e.g., `"00"` for quorum 0) |
| `quorum_threshold_percentage` | `Number` | No | BLS aggregation threshold (0-100) |
| `wasm_args` | `Array<Data>` | Yes | One entry per policy, in set order; `"0x"` for pure-Rego |
| `timeout` | `Number` | No | Timeout in seconds (default: 30) |
| `proof_cid` | `String` | No | IPFS CID of a TLSNotary presentation proof for zkTLS-backed policy evaluation |
| `include_validate_calldata` | `Boolean` | No | Include ABI-encoded `validateAttestationDirect` calldata in the response (default: false) |

:::warning
Some policy clients and identity-backed flows require `intent_signature` even though the RPC schema marks it optional. Passing an empty signature such as `"0x"` can fail before policy evaluation with an error like `Failed to encode intent signature: 0x reason: expected exactly 65 bytes`.
:::

Sign the exact intent with EIP-712 before calling `newt_createTask`. For PolicyClients that expose EIP-5267, read the signing domain from the contract's `eip712Domain()` method so the signature is bound to the deployed client:

```ts
const EIP712_DOMAIN_ABI = [
  {
    type: "function",
    name: "eip712Domain",
    stateMutability: "view",
    inputs: [],
    outputs: [
      { name: "fields", type: "bytes1" },
      { name: "name", type: "string" },
      { name: "version", type: "string" },
      { name: "chainId", type: "uint256" },
      { name: "verifyingContract", type: "address" },
      { name: "salt", type: "bytes32" },
      { name: "extensions", type: "uint256[]" },
    ],
  },
] as const;

async function readEip712Domain(policyClient, publicClient) {
  try {
    const [, name, version, chainId, verifyingContract] =
      await publicClient.readContract({
        address: policyClient,
        abi: EIP712_DOMAIN_ABI,
        functionName: "eip712Domain",
      });

    return {
      name,
      version,
      chainId: Number(chainId),
      verifyingContract,
    };
  } catch {
    return null;
  }
}

const domain = await readEip712Domain(policyClient, publicClient);
if (!domain) {
  throw new Error(
    "This policy client does not expose an EIP-712 domain, so the app cannot sign an intent for it.",
  );
}

const intentSignature = await walletClient.signTypedData({
  account,
  domain,
  types: {
    Intent: [
      { name: "from", type: "address" },
      { name: "to", type: "address" },
      { name: "value", type: "uint256" },
      { name: "data", type: "bytes" },
      { name: "chainId", type: "uint256" },
      { name: "functionSignature", type: "bytes" },
    ],
  },
  primaryType: "Intent",
  message: {
    ...intent,
    value: BigInt(intent.value),
    chainId: BigInt(intent.chainId),
  },
});
```

For manual fallback, the typed-data domain must match the policy client's Solidity `EIP712(name, version)` constructor values and deployed address:

| Solidity / deployment value | EIP-712 domain field |
|---|---|
| `EIP712("NewtonPolicyWallet", "1")` first argument | `name: "NewtonPolicyWallet"` |
| `EIP712("NewtonPolicyWallet", "1")` second argument | `version: "1"` |
| Target chain | `chainId` |
| Deployed PolicyClient address | `verifyingContract` |

#### Returns

| Field | Type | Description |
|---|---|---|
| `task_id` | `Data` | 32-byte task identifier |
| `status` | `TaskStatus` | Final task status |
| `aggregation_response` | `Object` | BLS aggregation result (if successful) |
| `task` | `Object` | Full Task struct for `validateAttestationDirect` (if success) |
| `task_response` | `Object` | Full TaskResponse struct from aggregation (if success) |
| `reference_block` | `Number` | Block number when response was prepared (if success) |
| `expiration` | `Number` | Expiration block: `reference_block + policyConfig.expireAfter` |
| `validate_calldata` | `String` | ABI-encoded calldata for `validateAttestationDirect` (present when `include_validate_calldata` was true) |
| `operator_errors` | `Array` | Per-operator error details with `retryable` classification (present on quorum failure) |
| `error` | `String` | Error message (if failed) |
| `timestamp` | `Number` | Unix timestamp |

:::note
The `task`, `task_response`, `reference_block`, and `expiration` fields enable clients to call `validateAttestationDirect` optimistically without waiting for on-chain task submission. The `signature_data` field contains pre-built, chain-aware encoded bytes ready to pass directly to the contract.
:::

To look the task up later — its evaluation result, operator errors, and the policy data it was evaluated against — pass `task_id` to the [Explorer API](/developers/reference/explorer-api#get-a-task).

#### Example

:::code-group
```json [Request]
{
  "jsonrpc": "2.0",
  "method": "newt_createTask",
  "params": {
    "policy_client": "0x1234567890123456789012345678901234567890",
    "intent": {
      "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
      "to": "0xb1aD5f82407bC0f19f42b2614fb9083035a36b69",
      "value": "0x0",
      "data": "0xa9059cbb000000000000000000000000e42e3458283032c669c98e0d8f883a92fc64fe220000000000000000000000000000000000000000000000000000000000000001",
      "chain_id": "0xaa36a7",
      "function_signature": "0x7472616e7366657228616464726573732c75696e7432353629"
    },
    "intent_signature": "0x...",
    "wasm_args": ["0x", "0x"],
    "timeout": 30
  },
  "id": "7ca6621b-7aa4-4bb7-a896-1f2b58a18c78"
}
```

```json [Response (Success)]
{
  "jsonrpc": "2.0",
  "result": {
    "task_id": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
    "status": "success",
    "aggregation_response": {
      "task_response_digest": "0xabcd...",
      "non_signer_stakes_and_signature": { }
    },
    "task": {
      "taskId": "0x1234...",
      "policyClient": "0x1234567890123456789012345678901234567890",
      "policyId": "0x...",
      "policyRevision": 1,
      "initializationTimestamp": "0x...",
      "policies": [
        { "policy": "0x...", "config": { "policyParams": "0x7b7d", "expireAfter": 25 } },
        { "policy": "0x...", "config": { "policyParams": "0x7b7d", "expireAfter": 25 } }
      ],
      "taskCreatedBlock": 12345678,
      "quorumThresholdPercentage": 67,
      "intent": { },
      "intentSignature": "0x...",
      "wasmArgs": ["0x", "0x"],
      "quorumNumbers": "0x00"
    },
    "task_response": {
      "task_id": "0x1234...",
      "policy_client": "0x...",
      "policy_id": "0x...",
      "intent": { },
      "intent_signature": "0x...",
      "allowed": true,
      "policy_task_data": [
        { "policyId": "0x...", "policyAddress": "0x...", "policy": "0x...", "policyData": [] },
        { "policyId": "0x...", "policyAddress": "0x...", "policy": "0x...", "policyData": [] }
      ]
    },
    "reference_block": 12345700,
    "expiration": 12345800,
    "error": null,
    "timestamp": 1705123456
  },
  "id": "7ca6621b-7aa4-4bb7-a896-1f2b58a18c78"
}
```

```json [Response (Failure)]
{
  "jsonrpc": "2.0",
  "result": {
    "task_id": "0x1234567890abcdef...",
    "status": "failed",
    "aggregation_response": null,
    "error": "Policy evaluation failed: insufficient permissions",
    "timestamp": 1705123456
  },
  "id": "7ca6621b-7aa4-4bb7-a896-1f2b58a18c78"
}
```
:::

***

### newt\_sendTask

Submits a task asynchronously and returns immediately with a WebSocket subscription topic for receiving updates.

**Permission:** `RpcRead`

#### Parameters

| Field | Type | Required | Description |
|---|---|---|---|
| `policy_client` | `Address` | Yes | Policy client contract address |
| `intent` | `TaskIntent` | Yes | Transaction intent to evaluate |
| `intent_signature` | `Data` | No | Hex-encoded EIP-712 signature of the exact intent. Required by policies and identity flows that consume `input.intent_signature` |
| `quorum_number` | `Data` | No | Quorum numbers (hex bytes) |
| `quorum_threshold_percentage` | `Number` | No | BLS aggregation threshold (0-100) |
| `wasm_args` | `Array<Data>` | Yes | One entry per policy, in set order; `"0x"` for pure-Rego |
| `proof_cid` | `String` | No | IPFS CID of a TLSNotary presentation proof for zkTLS-backed policy evaluation |

#### Returns

| Field | Type | Description |
|---|---|---|
| `task_id` | `Data` | 32-byte task identifier |
| `subscription_topic` | `String` | WebSocket topic for task updates |
| `message` | `String` | Confirmation message |
| `timestamp` | `Number` | Unix timestamp |

#### Example

:::code-group
```json [Request]
{
  "jsonrpc": "2.0",
  "method": "newt_sendTask",
  "params": {
    "policy_client": "0x1234567890123456789012345678901234567890",
    "intent": {
      "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
      "to": "0xb1aD5f82407bC0f19f42b2614fb9083035a36b69",
      "value": "0x0",
      "data": "0xa9059cbb000000000000000000000000e42e3458283032c669c98e0d8f883a92fc64fe220000000000000000000000000000000000000000000000000000000000000001",
      "chain_id": "0xaa36a7",
      "function_signature": "0x7472616e7366657228616464726573732c75696e7432353629"
    },
    "intent_signature": "0x..."
  },
  "id": "7ca6621b-7aa4-4bb7-a896-1f2b58a18c78"
}
```

```json [Response]
{
  "jsonrpc": "2.0",
  "result": {
    "task_id": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
    "subscription_topic": "newton.task.0x1234567890abcdef...",
    "message": "Task submitted for async processing",
    "timestamp": 1705123456
  },
  "id": "7ca6621b-7aa4-4bb7-a896-1f2b58a18c78"
}
```
:::

#### WebSocket Updates

Connect to the WebSocket endpoint and subscribe to the returned topic:

```json
{
  "type": "subscribe",
  "id": "sub-1",
  "method": "newton.task.0x1234567890abcdef...",
  "params": null
}
```

Updates are received in the following format:

```json
{
  "type": "update",
  "subscription": "sub-1",
  "result": {
    "event": "success",
    "task_id": "0x1234567890abcdef...",
    "timestamp": 1705123460,
    "data": {
      "status": "success",
      "operator_responses": [],
      "result": { },
      "progress": 100
    }
  }
}
```

***

### newt\_simulateTask

Evaluates Rego locally on the gateway using provided oracle **outputs**. It resolves the client's current policy set; it does not execute WASM, contact an operator quorum, produce BLS signatures, or create an on-chain task. Reconfiguration changes what this endpoint evaluates: it is not historical replay of a task's frozen set.

**Permission:** `RpcRead`.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `policy_client` | `Address` | Yes | Configured PolicyClient |
| `chain_id` | `number` | Yes | Deployment chain ID |
| `intent` | `TaskIntent` | Yes | Intent to evaluate |
| `wasm_args` | `Array<Data>` | Yes | Preassembled oracle outputs, positionally aligned; `"0x"` for pure-Rego |

```json
{
  "jsonrpc": "2.0",
  "method": "newt_simulateTask",
  "params": {
    "policy_client": "0x3333333333333333333333333333333333333333",
    "chain_id": 11155111,
    "intent": {
      "from": "0x1111111111111111111111111111111111111111",
      "to": "0x2222222222222222222222222222222222222222",
      "value": "0x0",
      "data": "0x",
      "chain_id": "0xaa36a7",
      "function_signature": "0x"
    },
    "wasm_args": [
      "0x",
      "0x"
    ]
  },
  "id": "policy-set-example"
}
```

| Field | Type | Meaning |
|---|---|---|
| `success` | `boolean` | Evaluation completed without an error |
| `allowed` | `boolean \| null` | AND of every policy verdict; null on error |
| `policy_id` | `string \| null` | ID of the set evaluated |
| `policies` | `array \| null` | Ordered results: `policy_index`, `policy` address, `result`, `allowed`, `expire_after` |
| `error` | `string \| null` | Evaluation failure details |
| `parsed_intent` | `object \| null` | Decoded intent |

A completed denial is `success: true, allowed: false`. A simulation failure is `success: false, allowed: null`. Neither response carries a BLS attestation.

:::warning
SDK v1.2.2's `simulateTask` wrapper still sends the old `policy_task_data` request. Use raw RPC for this endpoint, or SDK `simulatePolicy` for WASM + Rego simulation.
:::

***

### newt\_storeEncryptedSecrets

Uploads encrypted secrets for a Policy contract. Secrets are validated against the on-chain schema and stored for use during task evaluation.

**Permission:** `RpcWrite`

#### Parameters

| Field | Type | Required | Description |
|---|---|---|---|
| `policy_client` | `Address` | Yes | Policy client contract address |
| `policy_address` | `Address` | Yes | Policy contract address |
| `chain_id` | `Number` | Yes | Deployment chain ID |
| `envelope` | `String` | Yes | JSON-serialized HPKE SecureEnvelope (produced by `storeEncryptedSecrets` in the SDK) |

#### Returns

| Field | Type | Description |
|---|---|---|
| `success` | `Boolean` | Whether upload succeeded |
| `schema` | `Object` | JSON schema used for validation (on success) |
| `error` | `String` | Error message (on failure) |

#### Encryption

Secrets are encrypted client-side using HPKE before upload. Use `storeEncryptedSecrets` from the SDK, which handles encryption automatically. See [Encrypting Secrets](/developers/advanced/encrypting-secrets) for the full workflow.

**Plaintext format (before encryption):**

```json
{
  "API_KEY": "sk-xxxxxxxxxxxxx",
  "ENDPOINT": "https://api.example.com"
}
```

#### Ownership Model

:::note
Only the on-chain owner of the PolicyClient contract (as returned by `getOwner()`) can upload or update secrets. Ownership is transferable on-chain via `setOwner()` or `transferOwnership()`.
:::

#### Example

:::code-group
```json [Request]
{
  "jsonrpc": "2.0",
  "method": "newt_storeEncryptedSecrets",
  "params": {
    "policy_client": "0x1234567890123456789012345678901234567890",
    "policy_address": "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd",
    "chain_id": 11155111,
    "envelope": "<json-serialized-hpke-secure-envelope>"
  },
  "id": "7ca6621b-7aa4-4bb7-a896-1f2b58a18c78"
}
```

```json [Response (Success)]
{
  "jsonrpc": "2.0",
  "result": {
    "success": true,
    "schema": {
      "type": "object",
      "properties": {
        "API_KEY": { "type": "string" },
        "ENDPOINT": { "type": "string", "format": "uri" }
      },
      "required": ["API_KEY", "ENDPOINT"]
    },
    "error": null
  },
  "id": "7ca6621b-7aa4-4bb7-a896-1f2b58a18c78"
}
```

```json [Response (Error - Ownership Violation)]
{
  "jsonrpc": "2.0",
  "result": {
    "success": false,
    "schema": null,
    "error": "policy_client is owned by a different user"
  },
  "id": "7ca6621b-7aa4-4bb7-a896-1f2b58a18c78"
}
```

```json [Response (Error - Schema Validation)]
{
  "jsonrpc": "2.0",
  "result": {
    "success": false,
    "schema": null,
    "error": "Secrets upload validation failed: missing required field 'API_KEY'"
  },
  "id": "7ca6621b-7aa4-4bb7-a896-1f2b58a18c78"
}
```
:::

***

### newt\_simulatePolicyData

Simulates PolicyData WASM execution with caller-provided secrets. Use this endpoint to iterate on WASM plugins before uploading production secrets.

**Permission:** `RpcRead`

**Authorization:** Rate limiting only. Any valid API key can call this endpoint. No ownership verification is performed because secrets are provided directly by the caller.

#### When to Use

* **Iterating on PolicyData WASM** before uploading production secrets
* **Testing WASM execution** with different secret configurations
* **Policies whose WASM does not require secrets** (secrets field is optional)

#### Workflow

1. Deploy a Policy contract with `wasmCid` and optional `secretsSchemaCid`
2. Call `newt_simulatePolicyData` with optional encrypted secrets to test
3. Once satisfied, upload production secrets via `newt_storeEncryptedSecrets`
4. Test full policy via `newt_simulatePolicy` or `newt_simulatePolicyDataWithClient`

#### Parameters

| Field | Type | Required | Description |
|---|---|---|---|
| `policy_address` | `Address` | Yes | Policy contract address |
| `secrets` | `Object` | No | HPKE SecureEnvelope JSON object; not base64 |
| `wasm_args` | `Data` | No | Hex-encoded WASM arguments |
| `chain_id` | `Number` | Yes | Chain ID for RPC provider resolution |

#### Returns

| Field | Type | Description |
|---|---|---|
| `success` | `Boolean` | Whether simulation succeeded |
| `policy_data` | `Object` | WASM execution result (on success) |
| `error` | `String` | Error message (on failure) |

The `policy_data` object contains:

| Field | Type | Description |
|---|---|---|
| `specifier` | `String` | WASM source identifier (IPFS CID) |
| `data` | `Object` | WASM output data |
| `timestamp` | `Number` | Execution timestamp |

#### Example

:::code-group
```json [Request (with secrets)]
{
  "jsonrpc": "2.0",
  "method": "newt_simulatePolicyData",
  "params": {
    "policy_address": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    "chain_id": 11155111,
    "secrets": {
      "enc": "<hex-encapsulated-key>",
      "ciphertext": "<hex-ciphertext>",
      "policy_client": "0x3333333333333333333333333333333333333333",
      "chain_id": 11155111,
      "recipient_pubkey": "<hex-recipient-public-key>"
    },
    "wasm_args": "0x7b22626173655f73796d626f6c223a22425443227d"
  },
  "id": "7ca6621b-7aa4-4bb7-a896-1f2b58a18c78"
}
```

```json [Request (without secrets)]
{
  "jsonrpc": "2.0",
  "method": "newt_simulatePolicyData",
  "params": {
    "policy_address": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    "chain_id": 11155111,
    "wasm_args": "0x7b22626173655f73796d626f6c223a22425443227d"
  },
  "id": "7ca6621b-7aa4-4bb7-a896-1f2b58a18c78"
}
```

```json [Response (Success)]
{
  "jsonrpc": "2.0",
  "result": {
    "success": true,
    "policy_data": {
      "specifier": "bafkreigh2akiscaill...",
      "data": {
        "base_symbol": "BTC",
        "quote_symbol": "USD",
        "price": 42000.5
      },
      "timestamp": 1705123456
    },
    "error": null
  },
  "id": "7ca6621b-7aa4-4bb7-a896-1f2b58a18c78"
}
```

```json [Response (Error)]
{
  "jsonrpc": "2.0",
  "result": {
    "success": false,
    "policy_data": null,
    "error": "WASM execution failed: missing required secret 'API_KEY'"
  },
  "id": "7ca6621b-7aa4-4bb7-a896-1f2b58a18c78"
}
```
:::

***

### newt\_simulatePolicyDataWithClient

Simulates PolicyData WASM execution with previously uploaded secrets. Use this endpoint to test that stored secrets work correctly before testing the full policy.

**Permission:** `RpcRead`

**Authorization:** Ownership verification required. The caller's API key must belong to the user who owns the `policy_client` address. Ownership is checked against the client; uploading secrets does not transfer ownership.

#### When to Use

* **Testing PolicyData WASM** with previously uploaded secrets
* **Verifying stored secrets** work correctly before using `newt_simulatePolicy`
* **Debugging policy failures** by testing individual PolicyData sources

#### Prerequisites

1. Deploy a Policy contract with `wasmCid` and optional `secretsSchemaCid`
2. Upload secrets via `newt_storeEncryptedSecrets` as the authorized owner
3. Call this endpoint to test with stored secrets

#### Parameters

| Field | Type | Required | Description |
|---|---|---|---|
| `policy_address` | `Address` | Yes | Policy contract address |
| `chain_id` | `Number` | Yes | Deployment chain ID |
| `policy_client` | `Address` | Yes | Policy client address (for ownership check + secrets lookup) |
| `wasm_args` | `Data` | No | Hex-encoded WASM arguments |

#### Returns

| Field | Type | Description |
|---|---|---|
| `success` | `Boolean` | Whether simulation succeeded |
| `policy_data` | `Object` | WASM execution result (on success) |
| `error` | `String` | Error message (on failure) |

#### Example

:::code-group
```json [Request]
{
  "jsonrpc": "2.0",
  "method": "newt_simulatePolicyDataWithClient",
  "params": {
    "policy_address": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    "chain_id": 11155111,
    "policy_client": "0x1234567890123456789012345678901234567890",
    "wasm_args": "0x7b22626173655f73796d626f6c223a22425443227d"
  },
  "id": "7ca6621b-7aa4-4bb7-a896-1f2b58a18c78"
}
```

```json [Response (Success)]
{
  "jsonrpc": "2.0",
  "result": {
    "success": true,
    "policy_data": {
      "specifier": "bafkreigh2akiscaill...",
      "data": {
        "base_symbol": "BTC",
        "quote_symbol": "USD",
        "price": 42000.5
      },
      "timestamp": 1705123456
    },
    "error": null
  },
  "id": "7ca6621b-7aa4-4bb7-a896-1f2b58a18c78"
}
```

```json [Response (Error - Unauthorized)]
{
  "jsonrpc": "2.0",
  "error": {
    "code": -32002,
    "message": "Authorization failed: policy client 0x1234... is owned by another user"
  },
  "id": "7ca6621b-7aa4-4bb7-a896-1f2b58a18c78"
}
```

```json [Response (Error - Missing Secrets)]
{
  "jsonrpc": "2.0",
  "result": {
    "success": false,
    "policy_data": null,
    "error": "No secrets found for policy_client 0x1234... and policy_data 0xaaaa.... Upload secrets via newt_storeEncryptedSecrets first, or use newt_simulatePolicyData with directly provided secrets."
  },
  "id": "7ca6621b-7aa4-4bb7-a896-1f2b58a18c78"
}
```
:::

***

### newt\_simulatePolicy

Runs the configured policy set's optional WASM oracles and then Rego in the gateway's in-process evaluator. Unlike `newt_simulateTask`, `wasm_args` contains oracle **inputs**. Policies and the client must already be deployed and configured. Parameters come from the client's set; this endpoint no longer accepts inline Rego, `policy_data`, `policy_params`, or an `entrypoint` override.

**Permission:** `RpcRead`; on-chain client ownership is checked, with the controlled read-only admin-key exception described above. The in-process evaluator must be configured. This endpoint does not produce quorum signatures or execute an application transaction.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `policy_client` | `Address` | Yes | Configured PolicyClient |
| `chain_id` | `number` | Yes | Deployment chain ID |
| `intent` | `TaskIntent` | Yes | Intent to evaluate |
| `wasm_args` | `Array<Data>` | Yes | One oracle input per policy; `"0x"` for pure-Rego |
| `intent_signature` | `Data` | No | Accepted request field; simulation does not prove live signature authorization |

```json
{
  "jsonrpc": "2.0",
  "method": "newt_simulatePolicy",
  "params": {
    "policy_client": "0x3333333333333333333333333333333333333333",
    "chain_id": 11155111,
    "intent": {
      "from": "0x1111111111111111111111111111111111111111",
      "to": "0x2222222222222222222222222222222222222222",
      "value": "0x0",
      "data": "0x",
      "chain_id": "0xaa36a7",
      "function_signature": "0x"
    },
    "wasm_args": [
      "0x",
      "0x"
    ]
  },
  "id": "policy-set-example"
}
```

| Field | Type | Meaning |
|---|---|---|
| `success` | `boolean` | Evaluation completed without an error |
| `allowed` | `boolean \| null` | AND of every policy verdict; null on error |
| `policy_id` | `string \| null` | ID of the set evaluated |
| `policies` | `array \| null` | Ordered results: `policy_index`, `policy` address, `result`, `allowed`, `expire_after` |
| `error` | `string \| null` | Evaluation failure details |
| `parsed_intent` | `object \| null` | Decoded intent |

A completed denial is `success: true, allowed: false`. A simulation failure is `success: false, allowed: null`. Neither response carries a BLS attestation.

Use `policies[i].policy_index` and `policies[i].policy` to map each verdict back to the configured order. For production evaluation and signatures, use `newt_createTask` or `newt_sendTask` and subsequently validate the attestation on-chain.

***

### newt\_registerWebhook

Registers a webhook URL to receive failure notifications for tasks created with this API key.

#### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `url` | `string` | Yes | HTTPS URL to receive notifications |
| `secret` | `string` | No | HMAC secret for payload signing (recommended) |
| `timeout_seconds` | `number` | No | Request timeout in seconds (default: 10) |
| `max_retries` | `number` | No | Maximum retry attempts (default: 3) |
| `failure_types` | `string[]` | No | Failure types to notify about (default: all) |

**Failure Types:**

* `channel_error` -- Internal channel communication failures
* `timeout` -- Task processing timed out
* `quorum_not_reached` -- Insufficient operator signatures
* `onchain_submission_failed` -- Blockchain submission failed
* `policy_evaluation_failed` -- Policy evaluation error
* `signature_verification_failed` -- BLS signature verification error
* `internal_error` -- Unexpected internal error

#### Example

:::code-group
```json [Request]
{
  "jsonrpc": "2.0",
  "method": "newt_registerWebhook",
  "params": {
    "url": "https://api.example.com/newton/webhook",
    "secret": "your-hmac-secret-here",
    "failure_types": ["timeout", "quorum_not_reached", "onchain_submission_failed"]
  },
  "id": "7ca6621b-7aa4-4bb7-a896-1f2b58a18c78"
}
```

```json [Response]
{
  "jsonrpc": "2.0",
  "result": {
    "success": true,
    "message": "Webhook registered for https://api.example.com/newton/webhook"
  },
  "id": "7ca6621b-7aa4-4bb7-a896-1f2b58a18c78"
}
```
:::

***

### newt\_unregisterWebhook

Removes the webhook configuration for this API key.

**Parameters:** None

#### Example

:::code-group
```json [Request]
{
  "jsonrpc": "2.0",
  "method": "newt_unregisterWebhook",
  "params": {},
  "id": "7ca6621b-7aa4-4bb7-a896-1f2b58a18c78"
}
```

```json [Response]
{
  "jsonrpc": "2.0",
  "result": {
    "success": true,
    "message": "Webhook unregistered"
  },
  "id": "7ca6621b-7aa4-4bb7-a896-1f2b58a18c78"
}
```
:::

***

## Failure Notifications

The Newton Gateway provides real-time failure notifications through two channels: WebSocket subscriptions and webhook callbacks. Use WebSocket for real-time UI updates and webhooks for reliable server-to-server notifications.

### WebSocket Notifications

WebSocket notifications are best for:

* Real-time UI updates in browser applications
* Low-latency notification requirements
* Clients that maintain persistent connections

When subscribed to a task via WebSocket, failure notifications are delivered as JSON messages containing the full `TaskFailureNotification` payload.

### Webhook Callbacks

Webhook callbacks are best for:

* Server-to-server integrations
* Reliable delivery with automatic retries
* Auditable notification history
* Clients that cannot maintain persistent connections

**Webhook Request Format:**

The gateway sends POST requests to your registered URL with the following structure:

:::details[Webhook Payload]
```json
{
  "notification_id": "uuid-v4-unique-id",
  "task_id": "0x1234...",
  "timestamp": "2024-01-15T10:30:00Z",
  "failure_type": "quorum_not_reached",
  "error_message": "Quorum not reached: only 45% stake signed (required: 67%)",
  "context": {
    "signed_stake": "45000000000000000000",
    "required_stake": "67000000000000000000",
    "operator_count": 3
  },
  "is_recoverable": false,
  "retry_after_seconds": null
}
```
:::

**Security Headers:**

| Header | Description |
|---|---|
| `X-Newton-Signature` | HMAC-SHA256 signature (if secret configured) |
| `X-Idempotency-Key` | Unique notification ID for deduplication |
| `Content-Type` | `application/json` |

**Signature Verification:**

```python
import hmac
import hashlib

def verify_signature(payload: bytes, signature: str, secret: str) -> bool:
    expected = "sha256=" + hmac.new(
        secret.encode(),
        payload,
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(signature, expected)
```

**Retry Behavior:**

* Initial retry after 100ms with exponential backoff
* Maximum 3 retry attempts (configurable)
* Backoff capped at 10 seconds
* 4xx client errors (except 429) are not retried

***

## Developer Workflow

### Policy Development Lifecycle

1. Test Rego and optional WASM locally.
2. Deploy independent policies and configure the ordered set on the client.
3. Upload policy-scoped secrets when needed; test individual WASM modules with scalar-argument simulation endpoints.
4. Run `newt_simulatePolicy` for WASM + Rego, or `newt_simulateTask` with precomputed outputs. Neither produces signatures.
5. Sign the exact intent and submit `newt_createTask` or `newt_sendTask` for live operator evaluation.
6. Check aggregate `allowed` and validate the signed response on-chain before application execution.
7. Preserve task snapshots for historical investigation. Current-set simulation is not historical replay.

For required cases and evidence, see [Testing Policies](/developers/guides/testing-policies#policy-set-validation-checklist).

## Error Codes

### JSON-RPC Standard Errors

| Code | Message | Description |
|---|---|---|
| -32700 | Parse error | Invalid JSON |
| -32600 | Invalid request | Invalid JSON-RPC structure |
| -32601 | Method not found | Unknown RPC method |
| -32602 | Invalid params | Invalid method parameters |
| -32603 | Internal error | Server error |

### Newton-Specific Error Codes

| Code | Name | Description |
|---|---|---|
| -32615 | PolicyEvaluationError | Policy evaluation failed |
| -32616 | ContractError | Smart contract interaction error |
| -32617 | OperatorNotRegistered | Operator is not registered with the AVS |
| -32618 | IncompatiblePolicyVersion | Policy version mismatch between client/server |
| -32619 | IncompatiblePolicyDataVersion | Policy data version mismatch |
| -32620 | DataProviderError | Error fetching policy data from data provider |

### Newton-Specific Error Messages

| Error Message | Cause | Resolution |
|---|---|---|
| `"Unknown Newton RPC method: {method}"` | Invalid method name | Check method spelling |
| `"Invalid request format: {details}"` | Malformed parameters | Review parameter types |
| `"RpcRead permission required"` | Missing read permission | Use key with RpcRead |
| `"RpcWrite permission required"` | Missing write permission | Use key with RpcWrite |
| `"Invalid API key"` | Invalid or expired key | Verify API key |
| `"policy client {addr} is owned by another user"` | Ownership violation | Use API key that owns the policy\_client |
| `"policy client {addr} has no owner..."` | No ownership established | Upload secrets first via `newt_storeEncryptedSecrets` |
| `"Missing secrets for N PolicyData contract(s)"` | Secrets not uploaded | Upload secrets via `newt_storeEncryptedSecrets` |
| `"No secrets found for policy_client ... and policy_data..."` | Secrets not uploaded for pair | Upload secrets or use `newt_simulatePolicyData` instead |
| `"Secrets upload validation failed: {details}"` | Schema validation failure | Fix secrets format |
| `"WASM execution failed: {details}"` | WASM runtime error | Check WASM and inputs |
| `"Rego evaluation failed: {details}"` | Policy syntax/runtime error | Fix Rego code |
| `"Contract read failed: {details}"` | On-chain read error | Verify contract addresses |
| `"Task timeout"` | Aggregation timeout | Increase timeout or retry |

### HTTP Status Codes

| Status | Description |
|---|---|
| 200 | Success (check JSON-RPC result for errors) |
| 401 | Unauthorized - Invalid API key |
| 403 | Forbidden - Insufficient permissions |
| 429 | Too Many Requests - Rate limited |
| 500 | Internal Server Error |
| 502 | Bad Gateway - Service unavailable |

***

### Two HPKE Public Key Domains

Newton exposes two distinct HPKE public key endpoints. Using the wrong one causes silent decryption failures in threshold mode.

| Endpoint | Use For | Key Behavior |
|----------|---------|--------------|
| `newt_getPrivacyPublicKey` | Identity data, confidential data, ephemeral data | Threshold master public key (MPK) when DKG is active; otherwise individual operator key |
| `newt_getSecretsPublicKey` | WASM secrets (API keys, config for data providers) | Always the individual operator's key |

**Why two keys?** WASM secrets are decrypted during the Prepare phase when operators fetch policy data independently. In threshold mode, the threshold MPK cannot be decrypted until the Commit phase (after partial DH outputs are collected). Secrets encrypted to the threshold MPK would be undecryptable during Prepare, deadlocking the protocol. `newt_getSecretsPublicKey` always returns the individual operator's key to avoid this.

In single-node deployments, both keys may be identical. In production threshold DKG deployments, they differ.

### newt\_getPrivacyPublicKey

:::note
This method is under active development and not yet available in production. The API surface may change.
:::

Retrieves the system's threshold HPKE public key for encrypting data. Use this key to create a `SecureEnvelope` for sensitive data that operators threshold-decrypt during task evaluation.

**Permission:** `RpcRead`

#### Parameters

None.

#### Returns

| Field | Type | Description |
|---|---|---|
| `public_key` | `String` | Hex-encoded X25519 public key (32 bytes) |
| `key_type` | `String` | Key type identifier (`"x25519"`) |
| `encryption_suite` | `String` | Full cipher suite identifier |

#### Example

:::code-group
```json [Request]
{
  "jsonrpc": "2.0",
  "method": "newt_getPrivacyPublicKey",
  "params": {},
  "id": "7ca6621b-7aa4-4bb7-a896-1f2b58a18c78"
}
```

```json [Response]
{
  "jsonrpc": "2.0",
  "result": {
    "public_key": "<hex-encoded X25519 public key>",
    "key_type": "x25519",
    "encryption_suite": "HPKE-Base-X25519-HKDF-SHA256-ChaCha20Poly1305"
  },
  "id": "7ca6621b-7aa4-4bb7-a896-1f2b58a18c78"
}
```
:::

See [Privacy Layer](/developers/concepts/privacy-layer) for details on HPKE encryption.

***

### newt\_getSecretsPublicKey

Retrieves the HPKE public key used for encrypting WASM secrets. In threshold DKG mode, this may differ from the privacy public key returned by `newt_getPrivacyPublicKey`.

**Permission:** `RpcRead`

#### Parameters

None.

#### Returns

| Field | Type | Description |
|---|---|---|
| `public_key` | `String` | Hex-encoded X25519 public key (32 bytes) |
| `key_type` | `String` | Key type identifier (`"x25519"`) |
| `encryption_suite` | `String` | Full cipher suite identifier |

#### Example

:::code-group
```json [Request]
{
  "jsonrpc": "2.0",
  "method": "newt_getSecretsPublicKey",
  "params": {},
  "id": "7ca6621b-7aa4-4bb7-a896-1f2b58a18c78"
}
```

```json [Response]
{
  "jsonrpc": "2.0",
  "result": {
    "public_key": "<hex-encoded X25519 public key>",
    "key_type": "x25519",
    "encryption_suite": "HPKE-Base-X25519-HKDF-SHA256-ChaCha20Poly1305"
  },
  "id": "7ca6621b-7aa4-4bb7-a896-1f2b58a18c78"
}
```
:::

:::note
Use `newt_getSecretsPublicKey` when encrypting WASM secrets via `storeEncryptedSecrets`. Use `newt_getPrivacyPublicKey` for identity and confidential data encryption.
:::

***

### newt\_uploadIdentityEncrypted

Uploads HPKE-encrypted identity data to the gateway. The gateway stores the encrypted envelope and returns a `data_ref_id`, gateway EIP-712 signature, and deadline for the on-chain `registerIdentityData` call.

**Permission:** `RpcWrite`

#### Parameters

| Field | Type | Required | Description |
|---|---|---|---|
| `identity_owner` | `Address` | Yes | The identity owner's address |
| `identity_owner_sig` | `String` | Yes | EIP-712 signature of the SecureEnvelope JSON by the identity owner |
| `envelope` | `String` | Yes | JSON-serialized HPKE SecureEnvelope |
| `identity_domain` | `Hex (bytes32)` | Yes | Identity domain hash (e.g., `keccak256("kyc")`) |
| `chain_id` | `Number` | Yes | Chain ID the identity registry lives on |

#### Returns

| Field | Type | Description |
|---|---|---|
| `data_ref_id` | `String` | Content-hash data reference ID: `keccak256(envelope_json_bytes)` |
| `gateway_signature` | `String` | Gateway EIP-712 signature for `registerIdentityData` on-chain call |
| `deadline` | `Number` | Signature expiration (unix timestamp) for `registerIdentityData` |

#### Example

:::code-group
```json [Request]
{
  "jsonrpc": "2.0",
  "method": "newt_uploadIdentityEncrypted",
  "params": {
    "identity_owner": "0x1234567890abcdef1234567890abcdef12345678",
    "identity_owner_sig": "0x...",
    "envelope": "{\"enc\":\"...\",\"ciphertext\":\"...\",\"policy_client\":\"0x...\",\"chain_id\":11155111,\"recipient_pubkey\":\"...\"}",
    "identity_domain": "0x...",
    "chain_id": 11155111
  },
  "id": "7ca6621b-7aa4-4bb7-a896-1f2b58a18c78"
}
```

```json [Response]
{
  "jsonrpc": "2.0",
  "result": {
    "data_ref_id": "0xabcdef1234567890...",
    "gateway_signature": "0x...",
    "deadline": 1705127056
  },
  "id": "7ca6621b-7aa4-4bb7-a896-1f2b58a18c78"
}
```
:::

After receiving the response, call `registerIdentityData` on the IdentityRegistry contract with the `data_ref_id`, `gateway_signature`, and `deadline`.

***

### newt\_getIdentityEncrypted

Fetches encrypted identity data by its content-hash reference ID. Used to resolve a `data_ref_id` (stored on-chain in IdentityRegistry) back to the actual encrypted data blob (stored off-chain in the gateway).

**Permission:** `RpcRead`

#### Parameters

| Field | Type | Required | Description |
|---|---|---|---|
| `data_ref_id` | `String` | Yes | Content-hash data reference ID |

#### Returns

| Field | Type | Description |
|---|---|---|
| `envelope` | `String` | The HPKE-encrypted identity data as a SecureEnvelope JSON string |
| `identity_domain` | `String` | The identity domain this data was registered under |
| `identity_owner` | `String` | The identity owner address |

#### Example

:::code-group
```json [Request]
{
  "jsonrpc": "2.0",
  "method": "newt_getIdentityEncrypted",
  "params": {
    "data_ref_id": "0xabcdef1234567890..."
  },
  "id": "7ca6621b-7aa4-4bb7-a896-1f2b58a18c78"
}
```

```json [Response]
{
  "jsonrpc": "2.0",
  "result": {
    "envelope": "{\"enc\":\"...\",\"ciphertext\":\"...\"}",
    "identity_domain": "0x...",
    "identity_owner": "0x1234567890abcdef1234567890abcdef12345678"
  },
  "id": "7ca6621b-7aa4-4bb7-a896-1f2b58a18c78"
}
```
:::

***

### newt\_uploadConfidentialData

Upload HPKE-encrypted confidential data (blacklists, allowlists, sanctions lists) for a registered provider. The gateway stores the encrypted envelope and returns a content-hash `data_ref_id`. The provider then publishes the `data_ref_id` on-chain via `ConfidentialDataRegistry.publishData()` and grants access to specific policy clients.

**Permission level:** `RpcWrite`

**Parameters:**

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `provider` | `Address` | Yes | Provider address (must be registered on ConfidentialDataRegistry) |
| `domain` | `Hex (bytes32)` | Yes | Domain identifier (e.g., `keccak256("newton.privacy.blacklist")`) |
| `envelope` | `string` | Yes | Serialized HPKE `SecureEnvelope` JSON |
| `chain_id` | `number` | Yes | Chain ID the data is scoped to |

:::code-group
```json [Request]
{
  "jsonrpc": "2.0",
  "method": "newt_uploadConfidentialData",
  "params": {
    "provider": "0x1234567890abcdef1234567890abcdef12345678",
    "domain": "0x6f389bcc4114a6f517365d26d1327865d8634fb1e896e1323e904058afbea0e0",
    "envelope": "{\"enc\":\"...\",\"ciphertext\":\"...\",\"policy_client\":\"0x...\",\"chain_id\":11155111,\"recipient_pubkey\":\"...\"}",
    "chain_id": 11155111
  },
  "id": "7ca6621b-7aa4-4bb7-a896-1f2b58a18c78"
}
```

```json [Response]
{
  "jsonrpc": "2.0",
  "result": {
    "success": true,
    "data_ref_id": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
    "error": null
  },
  "id": "7ca6621b-7aa4-4bb7-a896-1f2b58a18c78"
}
```
:::

The SDK's `uploadConfidentialData` function handles HPKE encryption and envelope construction automatically.

***

### newt\_getConfidentialData

Retrieve encrypted confidential data by its content-hash reference ID. Returns the stored HPKE envelope for operator-side decryption.

**Permission level:** `RpcRead`

**Parameters:**

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `data_ref_id` | `string` | Yes | Content-hash data reference ID from `uploadConfidentialData` |

:::code-group
```json [Request]
{
  "jsonrpc": "2.0",
  "method": "newt_getConfidentialData",
  "params": {
    "data_ref_id": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
  },
  "id": "7ca6621b-7aa4-4bb7-a896-1f2b58a18c78"
}
```

```json [Response]
{
  "jsonrpc": "2.0",
  "result": {
    "envelope": "{\"enc\":\"...\",\"ciphertext\":\"...\",\"policy_client\":\"0x...\",\"chain_id\":11155111,\"recipient_pubkey\":\"...\"}",
    "data_type": "confidential"
  },
  "id": "7ca6621b-7aa4-4bb7-a896-1f2b58a18c78"
}
```
:::

***

## Related Resources

* [SDK Reference](/developers/reference/sdk-reference) -- TypeScript SDK for interacting with Newton Protocol
* [Integration Guide](/developers/guides/integration-guide) -- Step-by-step guide for integrating Newton into your application
* [Open Policy Agent (Rego) Documentation](https://www.openpolicyagent.org/docs/latest/) -- Reference for writing Rego policies
* [JSON-RPC 2.0 Specification](https://www.jsonrpc.org/specification) -- Protocol specification
