# Ticksupply Rust Client

[![crates.io](https://img.shields.io/crates/v/ticksupply.svg)](https://crates.io/crates/ticksupply)
[![docs.rs](https://docs.rs/ticksupply/badge.svg)](https://docs.rs/ticksupply)

Official Rust client for the [Ticksupply](https://ticksupply.com) market data API.

## Installation

```toml
[dependencies]
ticksupply = "0.1"
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
```

Minimum Supported Rust Version: **1.75**.

## Quick Start

```rust
use ticksupply::Client;

#[tokio::main]
async fn main() -> ticksupply::Result<()> {
    // Reads TICKSUPPLY_API_KEY from the environment.
    let client = Client::new()?;

    for exchange in client.exchanges().list().await? {
        println!("{}: {}", exchange.code, exchange.display_name);
    }

    // Create a subscription.
    let sub = client.subscriptions().create(12_345).send().await?;

    // Manage it.
    client.subscriptions().pause(&sub.id).send().await?;
    client.subscriptions().resume(&sub.id).send().await?;
    client.subscriptions().delete(&sub.id).send().await?;

    Ok(())
}
```

## Configuration

| Field          | Default                           | How to set                                              |
|----------------|-----------------------------------|---------------------------------------------------------|
| `api_key`      | `$TICKSUPPLY_API_KEY` (required)  | `Client::with_api_key(...)` or `.api_key(...)`          |
| `base_url`     | `https://api.ticksupply.com/v1`   | `.base_url(...)`                                        |
| `timeout`      | 30 s                              | `.timeout(Duration::from_secs(60))`                     |
| `max_retries`  | 3                                 | `.max_retries(5)`                                       |
| `user_agent`   | `ticksupply-rust/<version>`       | `.user_agent("my-bot/1.2")` (appended to prefix)        |
| `http_client`  | internal `reqwest::Client`        | `.http_client(custom)` — for proxies / custom TLS       |

```rust
use std::time::Duration;
let client = ticksupply::Client::builder()
    .api_key("key_xxx.secret")
    .timeout(Duration::from_secs(60))
    .max_retries(5)
    .build()?;
```

## Resources

- `client.exchanges()` — exchanges and per-exchange instruments
- `client.datastreams()` — datastream catalog with filters across exchanges/instruments
- `client.subscriptions()` — manage subscriptions
- `client.exports()` — create and download historical exports
- `client.availability()` — query data availability
- `client.export_schemas()` — define and manage custom output schemas. Build a `SchemaContent` once and pass it to `create`, `update`, or the draft workflow (`create_draft` → `update_draft` → `publish_draft`). Use `client.export_schemas().for_id("sch_…")` for a handle that hosts the schema-relative ops without repeating the id. For ad-hoc one-off schemas, pass a `SchemaContent` to `client.exports().create(...).inline_content(...)` instead of saving it.
- `client.billing()` — inspect plan, access status, usage

## Error Handling

```rust
use ticksupply::{Client, Error};

async fn demo(client: &Client) {
    match client.subscriptions().get("sub_invalid").await {
        Ok(sub) => println!("{:?}", sub),
        Err(Error::NotFound { message, request_id }) => {
            eprintln!("not found: {message} (req_id={request_id:?})");
        }
        Err(Error::RateLimited { retry_after, .. }) => {
            eprintln!("backoff for {retry_after:?}s");
        }
        Err(e) => eprintln!("other error: {e}"),
    }
}
```

## Feature Flags

| Feature        | Default | Purpose                                                                |
|----------------|---------|------------------------------------------------------------------------|
| `chrono`       | yes     | Accept / produce `chrono::DateTime<Utc>` values.                       |
| `time`         | no      | Accept / produce `time::OffsetDateTime` values.                        |
| `rust_decimal` | no      | Parse `Decimal` wire values into `rust_decimal::Decimal` losslessly.   |

Disable defaults when you only need raw `i64` nanoseconds:

```toml
ticksupply = { version = "0.1", default-features = false }
```

## Development

```bash
cargo build --all-features
cargo test --all-features
cargo clippy --all-features -- -D warnings
cargo fmt --all
RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --all-features
```

## License

MIT
