> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rivi.software/llms.txt
> Use this file to discover all available pages before exploring further.

# Other languages

> Starter REST clients for Python, Go, .NET, Ruby, PHP, Kotlin, and Swift, and how to go further with OpenAPI.

Besides TypeScript, the SDK repository ships small REST clients for common backend and mobile languages. They are **starters**: they handle authentication, the station document, weather, traffic, and playback ingest. They return untyped JSON: a dictionary or map in most languages, `JsonElement` in .NET, and `JsonObject` in Kotlin.

They do not include GraphQL, the public realtime feed, content by slug, sorting and filters, the draft preview handoff, ETag caching, retries, or response validation. For the realtime feed, use the [TypeScript SDK](/radiotools/api-reference/sdks/typescript#realtime-updates) 0.3.0 or later, or follow the feed yourself. Where you need more, use one of these routes:

* **Resolve a resource link yourself.** The station document lists the `resources` hrefs for schedule, content, now playing, and so on. Call those paths with the same bearer token — see [Requests and response handling](/radiotools/api-reference/response-handling). For article URLs, look records up by slug with [`GET …/content/{type}/by-slug/{slug}`](/radiotools/api-reference/public-listener/get-content-record-by-slug).
* **Generate a typed client** from the [OpenAPI document](/radiotools/openapi.json) with your language's generator.
* **Call the [HTTP operations](/radiotools/api-reference/public-listener/get-station) directly.**
* **Follow the realtime feed** described by `station.resources.realtime`. See [Public realtime feed](/radiotools/api-reference/public-delivery#public-realtime-feed).

## Packages

| Language | Package | Requires | Notes |
| - | - | - | - |
| Python | `radiotools-sdk`, imported as `radiotools_sdk` | Python 3.11 or newer | `httpx` 0.28 or newer |
| Go | module `github.com/radiotools/radiotools-sdk-go`, package `radiotools` | Go 1.22 or newer | `net/http` |
| .NET | `RadioTools.Sdk` | .NET 8 | `HttpClient` |
| Ruby | `radiotools_sdk` | Ruby 3.2 or newer | `Net::HTTP`; no gemspec |
| PHP | `radiotools/sdk`, namespace `RadioTools\Sdk` | PHP 8.2 or newer | curl extension; PSR-4 autoload |
| Kotlin | package `com.radiotools.sdk`, group `com.radiotools` | JVM 17 | Kotlin/JVM with OkHttp and kotlinx.serialization; usable from Android |
| Swift | `RadioToolsSDK` | Swift 6 tools, iOS 16, macOS 13 | `URLSession` with async/await |

The starters live in the `packages/` folder of the [radiotools-sdk repository](https://github.com/rivi-software/radiotools-sdk). The repository's release workflow publishes only the npm packages, so the starters are not part of the 0.3.0 release group and have no registry release. Install them from the repository:

| Language | Install |
| - | - |
| Python | `pip install "git+https://github.com/rivi-software/radiotools-sdk.git#subdirectory=packages/sdk-python"` |
| Go | Copy `packages/sdk-go` and point to it with a `replace` directive in your `go.mod`. The module path does not match the repository location, so `go get` cannot fetch it. |
| .NET | Add a project reference to `packages/sdk-dotnet/RadioTools.Sdk.csproj`. |
| Ruby | Copy `packages/sdk-ruby/lib` into your load path and `require "radiotools_sdk"`. |
| PHP | Add `packages/sdk-php` as a Composer `path` repository, then `composer require "radiotools/sdk:@dev"`. |
| Kotlin | Include `packages/sdk-kotlin` as a Gradle module or copy its source. |
| Swift | Add `packages/sdk-swift` as a local package in Xcode or with `.package(path:)`. |

## What each client implements

| Method | Python | Go | .NET | Ruby | PHP | Kotlin | Swift |
| - | - | - | - | - | - | - | - |
| Get station | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
| Get now playing | — | — | — | — | — | Yes | Yes |
| Get weather | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
| Get traffic | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
| Report playback | Yes | Yes | Yes | Yes | Yes | Yes | Yes |

Python also defines `get_schemas`, `get_content`, `get_content_record`, `get_content_by_slug`, `get_schedule`, `get_programs`, `get_current_broadcast`, `get_now_playing`, and `get_track_history`, but they raise `NotImplementedError` until you extend them. Use the resource links from the station document, as above.

Weather and traffic read the station document first, so each call sends two requests.

## Configuration

Every client takes the base URL, station slug, and one or both tokens. Python, Go, .NET, Ruby, and PHP also have a helper that reads the shared [environment variables](/radiotools/api-reference/sdks#credentials); Kotlin and Swift do not. Weather and traffic return nothing when the station does not publish them.

### Python

```python theme={null}
from radiotools_sdk import RadioToolsStationClient

client = RadioToolsStationClient.from_env()
station = client.get_station()

result = client.report_playback(
    {"artist": "The Riverlights", "title": "Morning Sun", "durationSeconds": 210}
)
print(result["outcome"])
```

### Go

```go theme={null}
client, err := radiotools.StationClientFromEnv()
if err != nil {
    log.Fatal(err)
}
station, err := client.GetStation(ctx)
```

### .NET

```csharp theme={null}
using var client = StationClient.FromEnvironment();
var station = await client.GetStationAsync();
```

### Ruby

```ruby theme={null}
require "radiotools_sdk"

client = RadioTools::StationClient.from_env
station = client.get_station
```

### PHP

```php theme={null}
$client = \RadioTools\Sdk\StationClient::fromEnv();
$station = $client->getStation();
```

### Kotlin

```kotlin theme={null}
val client = StationClient.create(
    baseUrl = "https://radiotools.rivi.software",
    stationSlug = "radio-rivier",
    apiToken = System.getenv("RADIOTOOLS_API_TOKEN"),
)
val station = client.getStation()
```

The Kotlin methods block, so call them off the main thread on Android.

### Swift

```swift theme={null}
let client = try StationClient(
    baseURL: URL(string: "https://radiotools.rivi.software")!,
    stationSlug: "radio-rivier",
    apiToken: ProcessInfo.processInfo.environment["RADIOTOOLS_API_TOKEN"]
)
let station = try await client.getStation()
```

## Report playback from any language

Encoders and automation often run outside TypeScript. Every starter client has a playback method that posts to `POST /api/v1/integrations/playback`: `report_playback` in Python and Ruby, `ReportPlayback` in Go, `ReportPlaybackAsync` in .NET, and `reportPlayback` in PHP, Kotlin, and Swift. Each takes an optional station ID (in Go, pass `""` to skip it); without one, the client sends its station slug. The method needs the `ingest:write` token and follows the rules in [Now-playing ingest](/radiotools/api-reference/now-playing-ingest): send `artist` with `title`, or a `streamTitle`, keep the body under 8 KiB, and set a stable `eventId` so your own retries stay idempotent. Unlike the TypeScript SDK, these clients do not add an `eventId` or retry for you.

## Errors

The starters raise or return a generic error for non-success responses. They do not parse the RadioTools error body. If you need `error.code` and `requestId`, read the response body — see [Errors and versioning](/radiotools/api-reference/errors-and-versioning).

| Language | Error on a non-success response |
| - | - |
| Python | `httpx.HTTPStatusError` |
| Go | An `error` whose message holds the status and response body |
| .NET | `HttpRequestException` |
| Ruby | `RuntimeError` with the status and response body |
| PHP | `RuntimeException` with the status and response body |
| Kotlin | `IllegalStateException` with the status and response body |
| Swift | `RadioToolsSDKError.httpStatus(code, body)` |


## Related topics

- [SDKs](/radiotools/api-reference/sdks/index.md)
- [Station settings](/radiotools/station-admin/station-settings.md)
- [Account and stations](/radiotools/account-and-stations.md)
- [Onboarding checklist](/radiotools/station-admin/onboarding.md)
- [AI settings](/radiotools/station-admin/ai-settings.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.