# Usage Guide
This walkthrough shows how to bootstrap the SDK, configure authentication, and call common APIs.
## 1. Configure Credentials
Create a `.env` file or export environment variables:
```env
PORT_CLIENT_ID=your-client-id
PORT_CLIENT_SECRET=your-client-secret
# Optional overrides:
# PORT_TOKEN_URL=https://api.getport.io/oauth/token
# PORT_BASE_URL=https://api.getport.io
# PORT_REGION=us
# PORT_PROXY_URL=http://localhost:8080
```
If you already manage access tokens elsewhere, set `PORT_ACCESS_TOKEN` instead of client credentials.
## 2. Initialize the Client
Use `PortClient::from_env` for the simplest setup:
```rust,no_run
use port_sdk::PortClient;
# #[tokio::main]
# async fn main() -> Result<(), port_sdk::error::PortError> {
dotenvy::dotenv().ok();
let client = PortClient::from_env()?;
# Ok(())
# }
```
For custom wiring, build a config manually:
```rust,no_run
use port_sdk::{PortClient, PortConfig, PortRegion};
use port_sdk::auth::{AuthStrategy, ClientCredentialsOptions};
use url::Url;
let options = ClientCredentialsOptions {
client_id: "client-id".into(),
client_secret: "client-secret".into(),
token_url: Url::parse("https://api.getport.io/oauth/token")?,
scope: None,
audience: None,
minimum_ttl: std::time::Duration::from_secs(30),
};
let config = PortConfig::builder()
.region(PortRegion::Us)
.auth(AuthStrategy::ClientCredentials(options))
.build()?;
let client = PortClient::from_config(config)?;
```
### Using `.env` During Local Testing
1. Duplicate the template file and add your credentials:
```bash
cp .env.example .env
$EDITOR .env
```
2. Add either `PORT_CLIENT_ID`/`PORT_CLIENT_SECRET` (recommended) or `PORT_ACCESS_TOKEN`.
3. Run `cargo test` or `cargo run --example authentication-and-listing` to confirm the SDK can authenticate.
4. Toggle optional settings (timeouts, retries, tracing) in `.env` and rerun the commands to observe behaviour differences.
## 3. Call API Helpers
High-level helpers live in `port_sdk::apis` and accept typed payloads.
```rust,no_run
use port_sdk::apis::blueprints;
use port_sdk::client::Pagination;
use port_sdk::PortClient;
# #[tokio::main]
# async fn main() -> Result<(), port_sdk::error::PortError> {
let client = PortClient::from_env()?;
let page = Pagination::builder().per_page(20).build();
let results: serde_json::Value = blueprints::list(&client, Some(&page)).await?;
println!("blueprints: {results}");
# Ok(())
# }
```
You can also work with typed structs:
```rust,no_run
use port_sdk::apis::entities;
use port_sdk::types::entities::EntityRequest;
# #[tokio::main]
# async fn main() -> Result<(), port_sdk::error::PortError> {
let client = PortClient::from_env()?;
let request = EntityRequest::new("entity-1", "blueprint-1", None);
let response = entities::create(&client, "blueprint-1", &request).await?;
println!("created entity {}", response.identifier);
# Ok(())
# }
```
## 4. Handle Errors & Retries
All fallible operations return `Result<T, PortError>`. Match on the error to distinguish HTTP, API, or configuration issues.
```rust,no_run
match client.get::<serde_json::Value>("/blueprints").await {
Ok(data) => println!("blueprints: {data}"),
Err(port_sdk::error::PortError::Api { status, message, .. }) => {
eprintln!("API error {status}: {message}");
}
Err(other) => eprintln!("request failed: {other:?}"),
}
```
Enable the `retry` feature (default) to automatically retry `429`/`5xx` responses. Customize policies via `PortConfig::builder().retry(...)`.
## 5. Useful Tips
- Inject a custom `reqwest::Client` via `PortClientBuilder::http_client` when you need bespoke TLS or connection pooling.
- Feature flags:
- `retry` (default) for backoff/retry support.
- `telemetry` to instrument requests with `tracing`.
- `blocking` to expose `reqwest::blocking` variants (add as needed).
- The resource tracker (`PortClient::tracker`) helps clean up entities created during tests.
Refer back to this guide whenever you onboard a new service or script with the SDK.