> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://onepin.ai/docs/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://onepin.ai/docs/_mcp/server.

# Get Node Detail

GET https://api.onepin.ai/api/v1/nodes/{node_type}

Return full node definition and runtime configuration options for a node type.

**Deprecated:** use `GET /api/v2/nodes/{node_type}` instead. This v1 variant
inlines the full TTS model catalog under `options.models_by_provider`, which
creates a large response and couples clients to the catalog structure. The v2
endpoint replaces that inline tree with a `providers` HATEOAS href pointing to
the standalone `/api/v1/providers` catalog, so the model list is fetched lazily
only when needed.

Unlike `GET /nodes` (which returns only static port schemas), this endpoint
returns the runtime values a caller uses to configure a node: supported target
languages derived from deployment settings, the available model catalog, and a
HATEOAS link to the workspace-scoped voice list. Requires `X-Workspace-Id`.

Reference: https://onepin.ai/docs/reference/api-reference/nodes/get-node-detail-api-v-1-nodes-node-type-get

## Authentication

- `Authorization` header (bearer token, required) — Clerk JWT token

## Servers

- `https://api.onepin.ai` (prod, default)
- `https://dev-api.onepin.ai` (dev)

## Request

### Path parameters

- `node_type` (string, required)

### Headers

- `X-Workspace-Id` (string, optional, nullable)

## Response

### 200

Successful Response

- `data` (NodeDetailOut, required) — Full node definition + runtime options for the canvas node-config UI.
- `meta` (Meta, required)

## Errors

### 404 Not Found Error

Node type not found

- `error` (ApiErrorBody, required)
- `meta` (Meta, required)

### 422 Unprocessable Entity Error

Validation Error

- `detail` (list of ValidationError, optional)

## Types

### NodeDetailOut

Full node definition + runtime options for the canvas node-config UI.

- `node_type` (string, required)
- `display_name` (string, required)
- `description` (string, required)
- `version` (integer, required)
- `category` (enum, required) — High-level grouping for node types. Lives here (not in services/) so the schema layer has no upward dependency on the registry.
  - Allowed values: `source`, `operator`, `validation`, `output`, `decision`
- `inputs` (list of PortOut, required)
- `outputs` (list of PortOut, required)
- `beta` (boolean, optional, default: false) — Whether this node carries a "beta" badge. Read from the live catalog per request, so staff can graduate a node without a release. Display only — it never affects availability. The static examples in this spec do not carry it and always show `false`; use the actual response.
- `input_schema` (map from string to any, optional)
- `config_schema` (map from string to any, optional)
- `options` (map from string to NodeDetailOutOptions, optional)

### Meta

- `request_id` (string, required)
- `timestamp` (datetime, required)

### ApiErrorBody

- `code` (string, required)
- `message` (string, required)
- `details` (list of ApiErrorDetail, optional, default: [])

### ValidationError

- `loc` (list of ValidationErrorLocItems, required)
- `msg` (string, required)
- `type` (string, required)
- `input` (any, optional)
- `ctx` (ValidationErrorCtx, optional)

### PortOut

- `name` (string, required)
- `fields` (list of string, optional)

### NodeDetailOutOptions

- `kind`: `href` (NodeOptionHref)
  - `target` (string, required)
  - `method` (string, optional, default: GET)
  - `properties` (map from string to NodeOptionProperty, optional)
- `kind`: `inline` (NodeOptionInline)
  - `value` (NodeOptionInlineValue, required)

### ApiErrorDetail

- `field` (string, required)
- `message` (string, required)
- `line_numbers` (list of integer, optional, nullable)
- `min_chars` (integer, optional, nullable)

### ValidationErrorLocItems

### ValidationErrorCtx

### NodeOptionProperty

One filter/param in a HATEOAS link.

- `options` (list of EnumOption, required)

### NodeOptionInlineValue

### EnumOption

Single allowed value for a filter/param, with human-readable label.

- `value` (string, required)
- `display_name` (string, required)

## Examples

### source_script

**Response**

```json
{
  "data": {
    "node_type": "source_script",
    "display_name": "Script Input",
    "description": "Upload or type your script",
    "version": 1,
    "category": "source",
    "inputs": [],
    "outputs": [
      {
        "name": "lines",
        "fields": [
          "locale_code",
          "script"
        ]
      }
    ],
    "beta": false,
    "input_schema": {
      "properties": {},
      "required": [],
      "type": "object"
    },
    "config_schema": {
      "csv_column": {
        "anyOf": [
          {
            "maxLength": 200,
            "type": "string"
          },
          {
            "type": "null"
          }
        ]
      },
      "csv_has_header": {
        "default": true,
        "type": "boolean"
      },
      "input_mode": {
        "default": "plain",
        "enum": [
          "plain",
          "markup"
        ],
        "type": "string"
      },
      "input_type": {
        "enum": [
          "text",
          "file",
          "media"
        ],
        "type": "string"
      },
      "source_language": {
        "anyOf": [
          {
            "type": "string"
          },
          {
            "type": "null"
          }
        ]
      },
      "text": {
        "default": "",
        "maxLength": 500000,
        "type": "string"
      },
      "upload_ids": {
        "items": {
          "format": "uuid",
          "type": "string"
        },
        "maxItems": 50,
        "type": "array"
      }
    },
    "options": {}
  },
  "meta": {
    "request_id": "01ABC...",
    "timestamp": "2026-04-09T00:00:00Z"
  }
}
```

**SDK Code**

```python source_script
import requests

url = "https://api.onepin.ai/api/v1/nodes/node_type"

headers = {"Authorization": "Bearer <token>"}

response = requests.get(url, headers=headers)

print(response.json())
```

```javascript source_script
const url = 'https://api.onepin.ai/api/v1/nodes/node_type';
const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go source_script
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://api.onepin.ai/api/v1/nodes/node_type"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("Authorization", "Bearer <token>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby source_script
require 'uri'
require 'net/http'

url = URI("https://api.onepin.ai/api/v1/nodes/node_type")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'

response = http.request(request)
puts response.read_body
```

```java source_script
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://api.onepin.ai/api/v1/nodes/node_type")
  .header("Authorization", "Bearer <token>")
  .asString();
```

```php source_script
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://api.onepin.ai/api/v1/nodes/node_type', [
  'headers' => [
    'Authorization' => 'Bearer <token>',
  ],
]);

echo $response->getBody();
```

```csharp source_script
using RestSharp;

var client = new RestClient("https://api.onepin.ai/api/v1/nodes/node_type");
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Bearer <token>");
IRestResponse response = client.Execute(request);
```

```swift source_script
import Foundation

let headers = ["Authorization": "Bearer <token>"]

let request = NSMutableURLRequest(url: NSURL(string: "https://api.onepin.ai/api/v1/nodes/node_type")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### operator_translator

**Response**

```json
{
  "data": {
    "node_type": "operator_translator",
    "display_name": "Translator",
    "description": "Translate into other languages",
    "version": 2,
    "category": "operator",
    "inputs": [
      {
        "name": "lines",
        "fields": [
          "locale_code",
          "script"
        ]
      }
    ],
    "outputs": [
      {
        "name": "lines",
        "fields": [
          "locale_code",
          "script"
        ]
      }
    ],
    "beta": false,
    "input_schema": {
      "properties": {
        "lines": {
          "items": {
            "properties": {
              "locale_code": {
                "default": [
                  "en-us"
                ],
                "description": "Locale code for the line.",
                "items": {
                  "enum": [
                    "ko-kr",
                    "ja-jp",
                    "en-us"
                  ],
                  "type": "string"
                },
                "maxItems": 1,
                "title": "Locale code",
                "type": "array",
                "x-donut-ui": "locale-code"
              },
              "script": {
                "default": "",
                "description": "Line script or reference text.",
                "title": "Script",
                "type": "string",
                "x-donut-ui": "textarea"
              }
            },
            "required": [
              "locale_code",
              "script"
            ],
            "type": "object"
          },
          "minItems": 1,
          "title": "Lines",
          "type": "array"
        }
      },
      "required": [
        "lines"
      ],
      "type": "object"
    },
    "config_schema": {
      "target_languages": {
        "items": {
          "enum": [
            "ko-kr",
            "ja-jp",
            "en-us"
          ],
          "type": "string"
        },
        "maxItems": 30,
        "minItems": 1,
        "type": "array"
      }
    },
    "options": {
      "available_languages": {
        "kind": "inline",
        "value": [
          {
            "display_name": "Korean (South Korea)",
            "value": "ko-kr"
          },
          {
            "display_name": "Japanese (Japan)",
            "value": "ja-jp"
          },
          {
            "display_name": "English (United States)",
            "value": "en-us"
          }
        ]
      }
    }
  },
  "meta": {
    "request_id": "01ABC...",
    "timestamp": "2026-04-09T00:00:00Z"
  }
}
```

**SDK Code**

```python operator_translator
import requests

url = "https://api.onepin.ai/api/v1/nodes/node_type"

headers = {"Authorization": "Bearer <token>"}

response = requests.get(url, headers=headers)

print(response.json())
```

```javascript operator_translator
const url = 'https://api.onepin.ai/api/v1/nodes/node_type';
const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go operator_translator
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://api.onepin.ai/api/v1/nodes/node_type"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("Authorization", "Bearer <token>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby operator_translator
require 'uri'
require 'net/http'

url = URI("https://api.onepin.ai/api/v1/nodes/node_type")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'

response = http.request(request)
puts response.read_body
```

```java operator_translator
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://api.onepin.ai/api/v1/nodes/node_type")
  .header("Authorization", "Bearer <token>")
  .asString();
```

```php operator_translator
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://api.onepin.ai/api/v1/nodes/node_type', [
  'headers' => [
    'Authorization' => 'Bearer <token>',
  ],
]);

echo $response->getBody();
```

```csharp operator_translator
using RestSharp;

var client = new RestClient("https://api.onepin.ai/api/v1/nodes/node_type");
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Bearer <token>");
IRestResponse response = client.Execute(request);
```

```swift operator_translator
import Foundation

let headers = ["Authorization": "Bearer <token>"]

let request = NSMutableURLRequest(url: NSURL(string: "https://api.onepin.ai/api/v1/nodes/node_type")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### operator_normalizer

**Response**

```json
{
  "data": {
    "node_type": "operator_normalizer",
    "display_name": "Normalizer",
    "description": "Normalization",
    "version": 1,
    "category": "operator",
    "inputs": [
      {
        "name": "lines",
        "fields": [
          "locale_code",
          "script"
        ]
      }
    ],
    "outputs": [
      {
        "name": "lines",
        "fields": [
          "script"
        ]
      }
    ],
    "beta": false,
    "input_schema": {
      "properties": {
        "lines": {
          "items": {
            "properties": {
              "locale_code": {
                "default": [
                  "en-us"
                ],
                "description": "Locale code for the line.",
                "items": {
                  "enum": [
                    "ko-kr",
                    "ja-jp",
                    "en-us"
                  ],
                  "type": "string"
                },
                "maxItems": 1,
                "title": "Locale code",
                "type": "array",
                "x-donut-ui": "locale-code"
              },
              "script": {
                "default": "",
                "description": "Line script or reference text.",
                "title": "Script",
                "type": "string",
                "x-donut-ui": "textarea"
              }
            },
            "required": [
              "locale_code",
              "script"
            ],
            "type": "object"
          },
          "minItems": 1,
          "title": "Lines",
          "type": "array"
        }
      },
      "required": [
        "lines"
      ],
      "type": "object"
    },
    "config_schema": {
      "engine": {
        "const": "llm",
        "default": "llm",
        "type": "string"
      },
      "target_locale": {
        "anyOf": [
          {
            "type": "string"
          },
          {
            "type": "null"
          }
        ]
      }
    },
    "options": {}
  },
  "meta": {
    "request_id": "01ABC...",
    "timestamp": "2026-04-09T00:00:00Z"
  }
}
```

**SDK Code**

```python operator_normalizer
import requests

url = "https://api.onepin.ai/api/v1/nodes/node_type"

headers = {"Authorization": "Bearer <token>"}

response = requests.get(url, headers=headers)

print(response.json())
```

```javascript operator_normalizer
const url = 'https://api.onepin.ai/api/v1/nodes/node_type';
const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go operator_normalizer
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://api.onepin.ai/api/v1/nodes/node_type"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("Authorization", "Bearer <token>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby operator_normalizer
require 'uri'
require 'net/http'

url = URI("https://api.onepin.ai/api/v1/nodes/node_type")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'

response = http.request(request)
puts response.read_body
```

```java operator_normalizer
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://api.onepin.ai/api/v1/nodes/node_type")
  .header("Authorization", "Bearer <token>")
  .asString();
```

```php operator_normalizer
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://api.onepin.ai/api/v1/nodes/node_type', [
  'headers' => [
    'Authorization' => 'Bearer <token>',
  ],
]);

echo $response->getBody();
```

```csharp operator_normalizer
using RestSharp;

var client = new RestClient("https://api.onepin.ai/api/v1/nodes/node_type");
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Bearer <token>");
IRestResponse response = client.Execute(request);
```

```swift operator_normalizer
import Foundation

let headers = ["Authorization": "Bearer <token>"]

let request = NSMutableURLRequest(url: NSURL(string: "https://api.onepin.ai/api/v1/nodes/node_type")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### operator_generator

**Response**

```json
{
  "data": {
    "node_type": "operator_generator",
    "display_name": "Voice Generator",
    "description": "TTS engine - voice generation",
    "version": 3,
    "category": "operator",
    "inputs": [
      {
        "name": "lines",
        "fields": [
          "locale_code",
          "script"
        ]
      }
    ],
    "outputs": [
      {
        "name": "lines",
        "fields": [
          "audio_files"
        ]
      }
    ],
    "beta": false,
    "input_schema": {
      "properties": {
        "lines": {
          "items": {
            "properties": {
              "locale_code": {
                "default": [
                  "en-us"
                ],
                "description": "Locale code for the line.",
                "items": {
                  "enum": [
                    "ko-kr",
                    "ja-jp",
                    "en-us"
                  ],
                  "type": "string"
                },
                "maxItems": 1,
                "title": "Locale code",
                "type": "array",
                "x-donut-ui": "locale-code"
              },
              "script": {
                "default": "",
                "description": "Line script or reference text.",
                "title": "Script",
                "type": "string",
                "x-donut-ui": "textarea"
              }
            },
            "required": [
              "locale_code",
              "script"
            ],
            "type": "object"
          },
          "minItems": 1,
          "title": "Lines",
          "type": "array"
        }
      },
      "required": [
        "lines"
      ],
      "type": "object"
    },
    "config_schema": {
      "target_locale": {
        "anyOf": [
          {
            "type": "string"
          },
          {
            "type": "null"
          }
        ],
        "title": "Target Locale"
      },
      "voice_map": {
        "additionalProperties": {
          "items": {
            "description": "Per-language voice assignment for operator generation.",
            "properties": {
              "canonical_controls": {
                "anyOf": [
                  {
                    "additionalProperties": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "integer"
                        },
                        {
                          "type": "number"
                        }
                      ]
                    },
                    "type": "object"
                  },
                  {
                    "type": "null"
                  }
                ],
                "title": "Canonical Controls"
              },
              "catalog_voice_id": {
                "anyOf": [
                  {
                    "format": "uuid",
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "title": "Catalog Voice Id"
              },
              "model": {
                "maxLength": 200,
                "minLength": 1,
                "title": "Model",
                "type": "string"
              },
              "provider": {
                "maxLength": 100,
                "minLength": 1,
                "title": "Provider",
                "type": "string"
              },
              "provider_config": {
                "anyOf": [
                  {
                    "additionalProperties": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "integer"
                        },
                        {
                          "type": "number"
                        },
                        {
                          "type": "boolean"
                        }
                      ]
                    },
                    "type": "object"
                  },
                  {
                    "type": "null"
                  }
                ],
                "title": "Provider Config"
              },
              "voice_id": {
                "maxLength": 255,
                "minLength": 1,
                "title": "Voice Id",
                "type": "string"
              },
              "voice_name": {
                "anyOf": [
                  {
                    "maxLength": 255,
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "title": "Voice Name"
              }
            },
            "required": [
              "voice_id",
              "provider",
              "model"
            ],
            "title": "VoiceAssignment",
            "type": "object"
          },
          "type": "array"
        },
        "title": "Voice Map",
        "type": "object"
      }
    },
    "options": {
      "models_by_provider": {
        "kind": "inline",
        "value": {
          "cartesia": {
            "display_name": "Cartesia",
            "models": [
              {
                "config_schema": {},
                "display_name": "Sonic 2",
                "model": "sonic-2"
              }
            ]
          },
          "elevenlabs": {
            "display_name": "ElevenLabs",
            "models": [
              {
                "config_schema": {},
                "display_name": "Eleven Multilingual v2",
                "model": "eleven_multilingual_v2"
              },
              {
                "config_schema": {},
                "display_name": "Eleven Turbo v2",
                "model": "eleven_turbo_v2"
              }
            ]
          },
          "naver": {
            "display_name": "Naver",
            "models": [
              {
                "config_schema": {},
                "display_name": "Clova",
                "model": "clova"
              }
            ]
          },
          "respeecher": {
            "display_name": "Respeecher",
            "models": [
              {
                "config_schema": {},
                "display_name": "Real-Time TTS",
                "model": "real_time"
              }
            ]
          },
          "rime": {
            "display_name": "Rime",
            "models": [
              {
                "config_schema": {},
                "display_name": "Arcana v3",
                "model": "arcana"
              }
            ]
          }
        }
      },
      "voices": {
        "kind": "href",
        "target": "/api/v1/voices",
        "method": "GET",
        "properties": {
          "language": {
            "options": [
              {
                "value": "ko-kr",
                "display_name": "Korean (South Korea)"
              },
              {
                "value": "ja-jp",
                "display_name": "Japanese (Japan)"
              },
              {
                "value": "en-us",
                "display_name": "English (United States)"
              }
            ]
          },
          "model": {
            "options": [
              {
                "value": "arcana",
                "display_name": "Arcana v3"
              },
              {
                "value": "clova",
                "display_name": "Clova"
              },
              {
                "value": "eleven_multilingual_v2",
                "display_name": "Eleven Multilingual v2"
              },
              {
                "value": "eleven_turbo_v2",
                "display_name": "Eleven Turbo v2"
              },
              {
                "value": "real_time",
                "display_name": "Real-Time TTS"
              },
              {
                "value": "sonic-2",
                "display_name": "Sonic 2"
              }
            ]
          },
          "provider": {
            "options": [
              {
                "value": "cartesia",
                "display_name": "Cartesia"
              },
              {
                "value": "elevenlabs",
                "display_name": "ElevenLabs"
              },
              {
                "value": "naver",
                "display_name": "Naver"
              },
              {
                "value": "respeecher",
                "display_name": "Respeecher"
              },
              {
                "value": "rime",
                "display_name": "Rime"
              }
            ]
          }
        }
      }
    }
  },
  "meta": {
    "request_id": "01ABC...",
    "timestamp": "2026-04-09T00:00:00Z"
  }
}
```

**SDK Code**

```python operator_generator
import requests

url = "https://api.onepin.ai/api/v1/nodes/node_type"

headers = {"Authorization": "Bearer <token>"}

response = requests.get(url, headers=headers)

print(response.json())
```

```javascript operator_generator
const url = 'https://api.onepin.ai/api/v1/nodes/node_type';
const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go operator_generator
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://api.onepin.ai/api/v1/nodes/node_type"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("Authorization", "Bearer <token>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby operator_generator
require 'uri'
require 'net/http'

url = URI("https://api.onepin.ai/api/v1/nodes/node_type")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'

response = http.request(request)
puts response.read_body
```

```java operator_generator
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://api.onepin.ai/api/v1/nodes/node_type")
  .header("Authorization", "Bearer <token>")
  .asString();
```

```php operator_generator
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://api.onepin.ai/api/v1/nodes/node_type', [
  'headers' => [
    'Authorization' => 'Bearer <token>',
  ],
]);

echo $response->getBody();
```

```csharp operator_generator
using RestSharp;

var client = new RestClient("https://api.onepin.ai/api/v1/nodes/node_type");
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Bearer <token>");
IRestResponse response = client.Execute(request);
```

```swift operator_generator
import Foundation

let headers = ["Authorization": "Bearer <token>"]

let request = NSMutableURLRequest(url: NSURL(string: "https://api.onepin.ai/api/v1/nodes/node_type")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### operator_phoneme_injector

**Response**

```json
{
  "data": {
    "node_type": "operator_phoneme_injector",
    "display_name": "Phoneme Injector",
    "description": "Work out how each word should be pronounced in context, so the Pronunciation Check knows what's correct",
    "version": 1,
    "category": "operator",
    "inputs": [
      {
        "name": "lines",
        "fields": [
          "audio_files",
          "locale_code",
          "script"
        ]
      }
    ],
    "outputs": [
      {
        "name": "lines",
        "fields": [
          "phoneme_map"
        ]
      }
    ],
    "beta": false,
    "input_schema": {
      "properties": {
        "lines": {
          "items": {
            "properties": {
              "locale_code": {
                "default": [
                  "en-us"
                ],
                "description": "Locale code for the line.",
                "items": {
                  "enum": [
                    "ko-kr",
                    "ja-jp",
                    "en-us"
                  ],
                  "type": "string"
                },
                "maxItems": 1,
                "title": "Locale code",
                "type": "array",
                "x-donut-ui": "locale-code"
              },
              "script": {
                "default": "",
                "description": "Line script or reference text.",
                "title": "Script",
                "type": "string",
                "x-donut-ui": "textarea"
              }
            },
            "required": [
              "locale_code",
              "script"
            ],
            "type": "object"
          },
          "minItems": 1,
          "title": "Lines",
          "type": "array"
        }
      },
      "required": [
        "lines"
      ],
      "type": "object"
    },
    "config_schema": {
      "exclude_address_rows": {
        "default": true,
        "type": "boolean"
      },
      "llm_candidate_filter": {
        "default": true,
        "type": "boolean"
      },
      "max_ngram": {
        "default": 1,
        "maximum": 5,
        "minimum": 1,
        "type": "integer"
      },
      "use_derived_word_parts": {
        "default": true,
        "type": "boolean"
      }
    },
    "options": {}
  },
  "meta": {
    "request_id": "01ABC...",
    "timestamp": "2026-04-09T00:00:00Z"
  }
}
```

**SDK Code**

```python operator_phoneme_injector
import requests

url = "https://api.onepin.ai/api/v1/nodes/node_type"

headers = {"Authorization": "Bearer <token>"}

response = requests.get(url, headers=headers)

print(response.json())
```

```javascript operator_phoneme_injector
const url = 'https://api.onepin.ai/api/v1/nodes/node_type';
const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go operator_phoneme_injector
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://api.onepin.ai/api/v1/nodes/node_type"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("Authorization", "Bearer <token>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby operator_phoneme_injector
require 'uri'
require 'net/http'

url = URI("https://api.onepin.ai/api/v1/nodes/node_type")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'

response = http.request(request)
puts response.read_body
```

```java operator_phoneme_injector
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://api.onepin.ai/api/v1/nodes/node_type")
  .header("Authorization", "Bearer <token>")
  .asString();
```

```php operator_phoneme_injector
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://api.onepin.ai/api/v1/nodes/node_type', [
  'headers' => [
    'Authorization' => 'Bearer <token>',
  ],
]);

echo $response->getBody();
```

```csharp operator_phoneme_injector
using RestSharp;

var client = new RestClient("https://api.onepin.ai/api/v1/nodes/node_type");
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Bearer <token>");
IRestResponse response = client.Execute(request);
```

```swift operator_phoneme_injector
import Foundation

let headers = ["Authorization": "Bearer <token>"]

let request = NSMutableURLRequest(url: NSURL(string: "https://api.onepin.ai/api/v1/nodes/node_type")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### operator_pronunciation_corrector

**Response**

```json
{
  "data": {
    "node_type": "operator_pronunciation_corrector",
    "display_name": "Pronunciation Corrector",
    "description": "Automatically fix mispronounced words, keeping the same voice",
    "version": 1,
    "category": "operator",
    "inputs": [
      {
        "name": "lines",
        "fields": [
          "audio_files",
          "locale_code",
          "script"
        ]
      }
    ],
    "outputs": [
      {
        "name": "lines",
        "fields": [
          "audio_files"
        ]
      }
    ],
    "beta": false,
    "input_schema": {
      "properties": {
        "lines": {
          "items": {
            "properties": {
              "audio_upload_id": {
                "description": "Confirmed playground audio upload to hydrate into audio_files.",
                "format": "uuid",
                "title": "Audio file",
                "type": "string",
                "x-donut-hydrates": "audio_files",
                "x-donut-ui": "audio-upload",
                "x-donut-upload-category": "dictionary"
              },
              "locale_code": {
                "default": [
                  "en-us"
                ],
                "description": "Locale code for the line.",
                "items": {
                  "enum": [
                    "ko-kr",
                    "ja-jp",
                    "en-us"
                  ],
                  "type": "string"
                },
                "maxItems": 1,
                "title": "Locale code",
                "type": "array",
                "x-donut-ui": "locale-code"
              },
              "mispronounced": {
                "description": "Optional (standalone only): the words the corrector should re-splice and their target IPA. `index` is the 0-based position of the word in `script` split on whitespace. The execute endpoint wraps these into a PED verdict on the take hydrated from audio_upload_id, so you supply only these entries — not the validator_kind/has_error wrapper.",
                "items": {
                  "properties": {
                    "index": {
                      "title": "Token index",
                      "type": "integer"
                    },
                    "ipa_intended": {
                      "title": "Intended IPA",
                      "type": "string"
                    },
                    "word": {
                      "title": "Word",
                      "type": "string"
                    }
                  },
                  "required": [
                    "word",
                    "index",
                    "ipa_intended"
                  ],
                  "type": "object"
                },
                "title": "Mispronounced words",
                "type": "array",
                "x-donut-ui": "json"
              },
              "phoneme_map": {
                "additionalProperties": {
                  "type": "string"
                },
                "description": "Optional per-word IPA pronunciation overrides as a {word: IPA} object, e.g. {\"tomato\": \"təˈmɑːtoʊ\"}. This is the SOURCE of the corrected pronunciation: a flagged word present here is respliced with this IPA, and a flagged word absent from it is skipped rather than corrected against the detector's guess. In a workflow the phoneme injector attaches it; supply it directly to test standalone. OMIT the field entirely to fall back to the detector's ipa_intended — an EMPTY object means the dictionary was consulted and had nothing, so every flagged word is skipped as no_dictionary_entry.",
                "title": "Phoneme map",
                "type": "object",
                "x-donut-ui": "json"
              },
              "script": {
                "default": "",
                "description": "Line script or reference text.",
                "title": "Script",
                "type": "string",
                "x-donut-ui": "textarea"
              }
            },
            "required": [
              "audio_upload_id",
              "locale_code",
              "script"
            ],
            "type": "object"
          },
          "minItems": 1,
          "title": "Lines",
          "type": "array"
        }
      },
      "required": [
        "lines"
      ],
      "type": "object"
    },
    "config_schema": {
      "fallback_to_detector_ipa": {
        "default": true,
        "type": "boolean"
      },
      "n_candidates": {
        "default": 2,
        "maximum": 8,
        "minimum": 1,
        "type": "integer"
      },
      "seed": {
        "anyOf": [
          {
            "maximum": 2147483647,
            "minimum": 0,
            "type": "integer"
          },
          {
            "type": "null"
          }
        ]
      },
      "target_ipa_source": {
        "default": "dictionary",
        "description": "Which IPA the correction targets: \"dictionary\" reads the built-in pronunciation reference; \"ped\" trusts the pronunciation check's own transcription.",
        "enum": [
          "dictionary",
          "ped"
        ],
        "type": "string"
      }
    },
    "options": {}
  },
  "meta": {
    "request_id": "01ABC...",
    "timestamp": "2026-04-09T00:00:00Z"
  }
}
```

**SDK Code**

```python operator_pronunciation_corrector
import requests

url = "https://api.onepin.ai/api/v1/nodes/node_type"

headers = {"Authorization": "Bearer <token>"}

response = requests.get(url, headers=headers)

print(response.json())
```

```javascript operator_pronunciation_corrector
const url = 'https://api.onepin.ai/api/v1/nodes/node_type';
const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go operator_pronunciation_corrector
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://api.onepin.ai/api/v1/nodes/node_type"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("Authorization", "Bearer <token>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby operator_pronunciation_corrector
require 'uri'
require 'net/http'

url = URI("https://api.onepin.ai/api/v1/nodes/node_type")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'

response = http.request(request)
puts response.read_body
```

```java operator_pronunciation_corrector
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://api.onepin.ai/api/v1/nodes/node_type")
  .header("Authorization", "Bearer <token>")
  .asString();
```

```php operator_pronunciation_corrector
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://api.onepin.ai/api/v1/nodes/node_type', [
  'headers' => [
    'Authorization' => 'Bearer <token>',
  ],
]);

echo $response->getBody();
```

```csharp operator_pronunciation_corrector
using RestSharp;

var client = new RestClient("https://api.onepin.ai/api/v1/nodes/node_type");
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Bearer <token>");
IRestResponse response = client.Execute(request);
```

```swift operator_pronunciation_corrector
import Foundation

let headers = ["Authorization": "Bearer <token>"]

let request = NSMutableURLRequest(url: NSURL(string: "https://api.onepin.ai/api/v1/nodes/node_type")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### sink_preview

**Response**

```json
{
  "data": {
    "node_type": "sink_preview",
    "display_name": "Export",
    "description": "Export final audio",
    "version": 1,
    "category": "output",
    "inputs": [
      {
        "name": "lines",
        "fields": [
          "audio_files"
        ]
      }
    ],
    "outputs": [],
    "beta": false,
    "input_schema": {
      "properties": {
        "lines": {
          "items": {
            "properties": {
              "audio_upload_id": {
                "description": "Confirmed playground audio upload to hydrate into audio_files.",
                "format": "uuid",
                "title": "Audio file",
                "type": "string",
                "x-donut-hydrates": "audio_files",
                "x-donut-ui": "audio-upload",
                "x-donut-upload-category": "dictionary"
              }
            },
            "required": [
              "audio_upload_id"
            ],
            "type": "object"
          },
          "minItems": 1,
          "title": "Lines",
          "type": "array"
        }
      },
      "required": [
        "lines"
      ],
      "type": "object"
    },
    "config_schema": {
      "format": {
        "default": "wav",
        "enum": [
          "wav",
          "mp3"
        ],
        "type": "string"
      }
    },
    "options": {}
  },
  "meta": {
    "request_id": "01ABC...",
    "timestamp": "2026-04-09T00:00:00Z"
  }
}
```

**SDK Code**

```python sink_preview
import requests

url = "https://api.onepin.ai/api/v1/nodes/node_type"

headers = {"Authorization": "Bearer <token>"}

response = requests.get(url, headers=headers)

print(response.json())
```

```javascript sink_preview
const url = 'https://api.onepin.ai/api/v1/nodes/node_type';
const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go sink_preview
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://api.onepin.ai/api/v1/nodes/node_type"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("Authorization", "Bearer <token>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby sink_preview
require 'uri'
require 'net/http'

url = URI("https://api.onepin.ai/api/v1/nodes/node_type")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'

response = http.request(request)
puts response.read_body
```

```java sink_preview
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://api.onepin.ai/api/v1/nodes/node_type")
  .header("Authorization", "Bearer <token>")
  .asString();
```

```php sink_preview
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://api.onepin.ai/api/v1/nodes/node_type', [
  'headers' => [
    'Authorization' => 'Bearer <token>',
  ],
]);

echo $response->getBody();
```

```csharp sink_preview
using RestSharp;

var client = new RestClient("https://api.onepin.ai/api/v1/nodes/node_type");
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Bearer <token>");
IRestResponse response = client.Execute(request);
```

```swift sink_preview
import Foundation

let headers = ["Authorization": "Bearer <token>"]

let request = NSMutableURLRequest(url: NSURL(string: "https://api.onepin.ai/api/v1/nodes/node_type")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### validator_error_rate

**Response**

```json
{
  "data": {
    "node_type": "validator_error_rate",
    "display_name": "Word Accuracy",
    "description": "Target word accuracy check",
    "version": 1,
    "category": "validation",
    "inputs": [
      {
        "name": "lines",
        "fields": [
          "audio_files",
          "locale_code",
          "script"
        ]
      }
    ],
    "outputs": [
      {
        "name": "pass",
        "fields": [
          "validation"
        ]
      },
      {
        "name": "fail",
        "fields": [
          "retry_counts",
          "validation"
        ]
      }
    ],
    "beta": false,
    "input_schema": {
      "properties": {
        "lines": {
          "items": {
            "properties": {
              "audio_upload_id": {
                "description": "Confirmed playground audio upload to hydrate into audio_files.",
                "format": "uuid",
                "title": "Audio file",
                "type": "string",
                "x-donut-hydrates": "audio_files",
                "x-donut-ui": "audio-upload",
                "x-donut-upload-category": "dictionary"
              },
              "locale_code": {
                "default": [
                  "en-us"
                ],
                "description": "Locale code for the line.",
                "items": {
                  "enum": [
                    "ko-kr",
                    "ja-jp",
                    "en-us"
                  ],
                  "type": "string"
                },
                "maxItems": 1,
                "title": "Locale code",
                "type": "array",
                "x-donut-ui": "locale-code"
              },
              "script": {
                "default": "",
                "description": "Line script or reference text.",
                "title": "Script",
                "type": "string",
                "x-donut-ui": "textarea"
              }
            },
            "required": [
              "audio_upload_id",
              "locale_code",
              "script"
            ],
            "type": "object"
          },
          "minItems": 1,
          "title": "Lines",
          "type": "array"
        }
      },
      "required": [
        "lines"
      ],
      "type": "object"
    },
    "config_schema": {
      "max_retries": {
        "default": 3,
        "maximum": 50,
        "minimum": 1,
        "type": "integer"
      },
      "threshold": {
        "default": 93,
        "maximum": 99,
        "minimum": 70,
        "type": "number"
      }
    },
    "options": {}
  },
  "meta": {
    "request_id": "01ABC...",
    "timestamp": "2026-04-09T00:00:00Z"
  }
}
```

**SDK Code**

```python validator_error_rate
import requests

url = "https://api.onepin.ai/api/v1/nodes/node_type"

headers = {"Authorization": "Bearer <token>"}

response = requests.get(url, headers=headers)

print(response.json())
```

```javascript validator_error_rate
const url = 'https://api.onepin.ai/api/v1/nodes/node_type';
const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go validator_error_rate
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://api.onepin.ai/api/v1/nodes/node_type"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("Authorization", "Bearer <token>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby validator_error_rate
require 'uri'
require 'net/http'

url = URI("https://api.onepin.ai/api/v1/nodes/node_type")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'

response = http.request(request)
puts response.read_body
```

```java validator_error_rate
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://api.onepin.ai/api/v1/nodes/node_type")
  .header("Authorization", "Bearer <token>")
  .asString();
```

```php validator_error_rate
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://api.onepin.ai/api/v1/nodes/node_type', [
  'headers' => [
    'Authorization' => 'Bearer <token>',
  ],
]);

echo $response->getBody();
```

```csharp validator_error_rate
using RestSharp;

var client = new RestClient("https://api.onepin.ai/api/v1/nodes/node_type");
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Bearer <token>");
IRestResponse response = client.Execute(request);
```

```swift validator_error_rate
import Foundation

let headers = ["Authorization": "Bearer <token>"]

let request = NSMutableURLRequest(url: NSURL(string: "https://api.onepin.ai/api/v1/nodes/node_type")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### validator_naturalness

**Response**

```json
{
  "data": {
    "node_type": "validator_naturalness",
    "display_name": "Naturalness",
    "description": "Score naturalness of generated speech",
    "version": 1,
    "category": "validation",
    "inputs": [
      {
        "name": "lines",
        "fields": [
          "audio_files",
          "locale_code",
          "script"
        ]
      }
    ],
    "outputs": [
      {
        "name": "pass",
        "fields": [
          "validation"
        ]
      },
      {
        "name": "fail",
        "fields": [
          "retry_counts",
          "validation"
        ]
      }
    ],
    "beta": false,
    "input_schema": {
      "properties": {
        "lines": {
          "items": {
            "properties": {
              "audio_upload_id": {
                "description": "Confirmed playground audio upload to hydrate into audio_files.",
                "format": "uuid",
                "title": "Audio file",
                "type": "string",
                "x-donut-hydrates": "audio_files",
                "x-donut-ui": "audio-upload",
                "x-donut-upload-category": "dictionary"
              },
              "locale_code": {
                "default": [
                  "en-us"
                ],
                "description": "Locale code for the line.",
                "items": {
                  "enum": [
                    "ko-kr",
                    "ja-jp",
                    "en-us"
                  ],
                  "type": "string"
                },
                "maxItems": 1,
                "title": "Locale code",
                "type": "array",
                "x-donut-ui": "locale-code"
              },
              "script": {
                "default": "",
                "description": "Line script or reference text.",
                "title": "Script",
                "type": "string",
                "x-donut-ui": "textarea"
              }
            },
            "required": [
              "audio_upload_id",
              "locale_code",
              "script"
            ],
            "type": "object"
          },
          "minItems": 1,
          "title": "Lines",
          "type": "array"
        }
      },
      "required": [
        "lines"
      ],
      "type": "object"
    },
    "config_schema": {
      "max_retries": {
        "default": 3,
        "maximum": 50,
        "minimum": 1,
        "type": "integer"
      },
      "threshold": {
        "default": 70,
        "maximum": 100,
        "minimum": 0,
        "type": "number"
      }
    },
    "options": {}
  },
  "meta": {
    "request_id": "01ABC...",
    "timestamp": "2026-04-09T00:00:00Z"
  }
}
```

**SDK Code**

```python validator_naturalness
import requests

url = "https://api.onepin.ai/api/v1/nodes/node_type"

headers = {"Authorization": "Bearer <token>"}

response = requests.get(url, headers=headers)

print(response.json())
```

```javascript validator_naturalness
const url = 'https://api.onepin.ai/api/v1/nodes/node_type';
const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go validator_naturalness
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://api.onepin.ai/api/v1/nodes/node_type"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("Authorization", "Bearer <token>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby validator_naturalness
require 'uri'
require 'net/http'

url = URI("https://api.onepin.ai/api/v1/nodes/node_type")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'

response = http.request(request)
puts response.read_body
```

```java validator_naturalness
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://api.onepin.ai/api/v1/nodes/node_type")
  .header("Authorization", "Bearer <token>")
  .asString();
```

```php validator_naturalness
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://api.onepin.ai/api/v1/nodes/node_type', [
  'headers' => [
    'Authorization' => 'Bearer <token>',
  ],
]);

echo $response->getBody();
```

```csharp validator_naturalness
using RestSharp;

var client = new RestClient("https://api.onepin.ai/api/v1/nodes/node_type");
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Bearer <token>");
IRestResponse response = client.Execute(request);
```

```swift validator_naturalness
import Foundation

let headers = ["Authorization": "Bearer <token>"]

let request = NSMutableURLRequest(url: NSURL(string: "https://api.onepin.ai/api/v1/nodes/node_type")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### validator_noise

**Response**

```json
{
  "data": {
    "node_type": "validator_noise",
    "display_name": "Clarity",
    "description": "Check the clarity of generated audio (flags background noise / artifacts)",
    "version": 1,
    "category": "validation",
    "inputs": [
      {
        "name": "lines",
        "fields": [
          "audio_files",
          "locale_code",
          "script"
        ]
      }
    ],
    "outputs": [
      {
        "name": "pass",
        "fields": [
          "validation"
        ]
      },
      {
        "name": "fail",
        "fields": [
          "retry_counts",
          "validation"
        ]
      }
    ],
    "beta": false,
    "input_schema": {
      "properties": {
        "lines": {
          "items": {
            "properties": {
              "audio_upload_id": {
                "description": "Confirmed playground audio upload to hydrate into audio_files.",
                "format": "uuid",
                "title": "Audio file",
                "type": "string",
                "x-donut-hydrates": "audio_files",
                "x-donut-ui": "audio-upload",
                "x-donut-upload-category": "dictionary"
              },
              "locale_code": {
                "default": [
                  "en-us"
                ],
                "description": "Locale code for the line.",
                "items": {
                  "enum": [
                    "ko-kr",
                    "ja-jp",
                    "en-us"
                  ],
                  "type": "string"
                },
                "maxItems": 1,
                "title": "Locale code",
                "type": "array",
                "x-donut-ui": "locale-code"
              },
              "script": {
                "default": "",
                "description": "Line script or reference text.",
                "title": "Script",
                "type": "string",
                "x-donut-ui": "textarea"
              }
            },
            "required": [
              "audio_upload_id",
              "locale_code",
              "script"
            ],
            "type": "object"
          },
          "minItems": 1,
          "title": "Lines",
          "type": "array"
        }
      },
      "required": [
        "lines"
      ],
      "type": "object"
    },
    "config_schema": {
      "max_retries": {
        "default": 3,
        "maximum": 50,
        "minimum": 1,
        "type": "integer"
      },
      "threshold": {
        "default": 70,
        "maximum": 100,
        "minimum": 0,
        "type": "number"
      }
    },
    "options": {}
  },
  "meta": {
    "request_id": "01ABC...",
    "timestamp": "2026-04-09T00:00:00Z"
  }
}
```

**SDK Code**

```python validator_noise
import requests

url = "https://api.onepin.ai/api/v1/nodes/node_type"

headers = {"Authorization": "Bearer <token>"}

response = requests.get(url, headers=headers)

print(response.json())
```

```javascript validator_noise
const url = 'https://api.onepin.ai/api/v1/nodes/node_type';
const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go validator_noise
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://api.onepin.ai/api/v1/nodes/node_type"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("Authorization", "Bearer <token>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby validator_noise
require 'uri'
require 'net/http'

url = URI("https://api.onepin.ai/api/v1/nodes/node_type")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'

response = http.request(request)
puts response.read_body
```

```java validator_noise
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://api.onepin.ai/api/v1/nodes/node_type")
  .header("Authorization", "Bearer <token>")
  .asString();
```

```php validator_noise
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://api.onepin.ai/api/v1/nodes/node_type', [
  'headers' => [
    'Authorization' => 'Bearer <token>',
  ],
]);

echo $response->getBody();
```

```csharp validator_noise
using RestSharp;

var client = new RestClient("https://api.onepin.ai/api/v1/nodes/node_type");
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Bearer <token>");
IRestResponse response = client.Execute(request);
```

```swift validator_noise
import Foundation

let headers = ["Authorization": "Bearer <token>"]

let request = NSMutableURLRequest(url: NSURL(string: "https://api.onepin.ai/api/v1/nodes/node_type")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### validator_pronunciation

**Response**

```json
{
  "data": {
    "node_type": "validator_pronunciation",
    "display_name": "Pronunciation",
    "description": "Check each word is pronounced correctly, sound by sound",
    "version": 1,
    "category": "validation",
    "inputs": [
      {
        "name": "lines",
        "fields": [
          "audio_files",
          "locale_code",
          "script"
        ]
      }
    ],
    "outputs": [
      {
        "name": "pass",
        "fields": [
          "validation"
        ]
      },
      {
        "name": "fail",
        "fields": [
          "retry_counts",
          "validation"
        ]
      }
    ],
    "beta": false,
    "input_schema": {
      "properties": {
        "lines": {
          "items": {
            "properties": {
              "audio_upload_id": {
                "description": "Confirmed playground audio upload to hydrate into audio_files.",
                "format": "uuid",
                "title": "Audio file",
                "type": "string",
                "x-donut-hydrates": "audio_files",
                "x-donut-ui": "audio-upload",
                "x-donut-upload-category": "dictionary"
              },
              "locale_code": {
                "default": [
                  "en-us"
                ],
                "description": "Locale code for the line.",
                "items": {
                  "enum": [
                    "ko-kr",
                    "ja-jp",
                    "en-us"
                  ],
                  "type": "string"
                },
                "maxItems": 1,
                "title": "Locale code",
                "type": "array",
                "x-donut-ui": "locale-code"
              },
              "phoneme_map": {
                "additionalProperties": {
                  "type": "string"
                },
                "description": "Optional per-word IPA pronunciation overrides as a {word: IPA} object, e.g. {\"tomato\": \"təˈmɑːtoʊ\"}. In a workflow the phoneme injector attaches this on a validator's fail path; supply it directly to test this node standalone. Words absent from the map are graded by spelling.",
                "title": "Phoneme map",
                "type": "object",
                "x-donut-ui": "json"
              },
              "script": {
                "default": "",
                "description": "Line script or reference text.",
                "title": "Script",
                "type": "string",
                "x-donut-ui": "textarea"
              }
            },
            "required": [
              "audio_upload_id",
              "locale_code",
              "script"
            ],
            "type": "object"
          },
          "minItems": 1,
          "title": "Lines",
          "type": "array"
        }
      },
      "required": [
        "lines"
      ],
      "type": "object"
    },
    "config_schema": {
      "k": {
        "default": 1,
        "exclusiveMinimum": 0,
        "maximum": 10,
        "type": "number"
      },
      "max_retries": {
        "default": 3,
        "maximum": 50,
        "minimum": 1,
        "type": "integer"
      },
      "threshold": {
        "default": 99,
        "maximum": 100,
        "minimum": 0,
        "type": "number"
      }
    },
    "options": {}
  },
  "meta": {
    "request_id": "01ABC...",
    "timestamp": "2026-04-09T00:00:00Z"
  }
}
```

**SDK Code**

```python validator_pronunciation
import requests

url = "https://api.onepin.ai/api/v1/nodes/node_type"

headers = {"Authorization": "Bearer <token>"}

response = requests.get(url, headers=headers)

print(response.json())
```

```javascript validator_pronunciation
const url = 'https://api.onepin.ai/api/v1/nodes/node_type';
const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go validator_pronunciation
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://api.onepin.ai/api/v1/nodes/node_type"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("Authorization", "Bearer <token>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby validator_pronunciation
require 'uri'
require 'net/http'

url = URI("https://api.onepin.ai/api/v1/nodes/node_type")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'

response = http.request(request)
puts response.read_body
```

```java validator_pronunciation
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://api.onepin.ai/api/v1/nodes/node_type")
  .header("Authorization", "Bearer <token>")
  .asString();
```

```php validator_pronunciation
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://api.onepin.ai/api/v1/nodes/node_type', [
  'headers' => [
    'Authorization' => 'Bearer <token>',
  ],
]);

echo $response->getBody();
```

```csharp validator_pronunciation
using RestSharp;

var client = new RestClient("https://api.onepin.ai/api/v1/nodes/node_type");
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Bearer <token>");
IRestResponse response = client.Execute(request);
```

```swift validator_pronunciation
import Foundation

let headers = ["Authorization": "Bearer <token>"]

let request = NSMutableURLRequest(url: NSURL(string: "https://api.onepin.ai/api/v1/nodes/node_type")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```