Command Palette
Search for a command to run...

Rust SDK (Community)

Use the community-maintained notra crate for a type-safe Rust integration.

reference · intermediate · 12m
gilt für notra-api, rust
von Dominik K. ·

The notra crate is a community-maintained Rust SDK for the Notra API. It provides typed request builders, response structs, and async support via tokio.

Info

This SDK is community-maintained. Source and docs are available at crates.io/crates/notra and GitHub.

Installation

Add the crate to your Cargo.toml:

[dependencies]notra = "0.1.1"tokio = { version = "1", features = ["full"] }

Quick Start

use notra::Notra;#[tokio::main]async fn main() -> Result<(), notra::NotraError> {    let notra = Notra::builder()        .bearer_auth(std::env::var("NOTRA_API_KEY").unwrap())        .build()?;    let result = notra.content()        .list_posts()        .send()        .await?;    for post in &result.posts {        println!("{} ({})", post.title, post.id);    }    Ok(())}

Authentication

Pass your API key via the builder:

use notra::Notra;let notra = Notra::builder()    .bearer_auth(std::env::var("NOTRA_BEARER_AUTH").unwrap())    .build()?;

You can also configure a custom base URL and timeout:

use std::time::Duration;use notra::Notra;let notra = Notra::builder()    .bearer_auth("your-api-key")    .server_url("https://api.usenotra.com") // default    .timeout(Duration::from_secs(60))       // default: 30s    .build()?;

Posts

List posts

use notra::Notra;use notra::models::{PostStatus, Sort};let result = notra.content()    .list_posts()    .status(PostStatus::Published)    .sort(Sort::Desc)    .limit(10)    .page(1)    .send()    .await?;for post in &result.posts {    println!("{}", post.title);}println!(    "Page {} of {}",    result.pagination.current_page,    result.pagination.total_pages.unwrap_or(1));

Get a single post

let result = notra.content()    .get_post("post_abc")    .send()    .await?;if let Some(post) = result.post {    println!("{}: {}", post.title, post.status);}

Update a post

use notra::models::PostStatus;let updated = notra.content()    .update_post("post_abc")    .title("Ship notes for week 11")    .markdown("# Ship notes\n\nWe shipped a faster editor.")    .status(PostStatus::Published)    .send()    .await?;println!("{:?}", updated.post);

Delete a post

notra.content()    .delete_post("post_abc")    .send()    .await?;

Post Generation

Queue a generation job

use notra::models::*;let job = notra.content()    .create_post_generation(ContentType::Changelog)    .lookback_window(LookbackWindow::Last7Days)    .brand_identity_id("brand-id")    .github_integration_ids(vec!["integration-1".into()])    .repositories(vec![        Repository { owner: "my-org".into(), repo: "my-repo".into() },    ])    .data_points(DataPoints {        commits: true,        pull_requests: true,        releases: true,        linear_data: false,    })    .send()    .await?;println!("Job started: {}", job.job.id);

Poll job status

let status = notra.content()    .get_post_generation("job-id")    .send()    .await?;println!("Status: {:?}", status.job.status);for event in &status.events {    println!("  {} at {}", event.event_type, event.created_at);}

Brand Identities

List brand identities

let result = notra.content()    .list_brand_identities()    .send()    .await?;for bi in &result.brand_identities {    println!("{} (default: {})", bi.name, bi.is_default);}

Generate a brand identity from a website

let job = notra.content()    .create_brand_identity("https://example.com")    .name("My Brand")    .send()    .await?;// Poll for completionlet status = notra.content()    .get_brand_identity_generation(&job.job.id)    .send()    .await?;println!("Step: {:?}, Status: {:?}", status.job.current_step, status.job.status);

Update a brand identity

use notra::models::{ToneProfile, Language};let updated = notra.content()    .update_brand_identity("identity-id")    .name("Updated Brand")    .tone_profile(ToneProfile::Professional)    .language(Language::English)    .audience("Developers")    .is_default(true)    .send()    .await?;

Delete a brand identity

notra.content()    .delete_brand_identity("identity-id")    .send()    .await?;

Integrations

List integrations

let integrations = notra.content()    .list_integrations()    .send()    .await?;for gh in &integrations.github {    println!("{}/{} ({})", gh.owner, gh.repo, gh.default_branch);}

Connect a GitHub repository

let gh = notra.content()    .create_github_integration("my-org", "my-repo")    .branch("main")    .auth_token("ghp_xxx") // optional, for private repos    .send()    .await?;println!("Connected: {}", gh.github.display_name);

Disconnect an integration

notra.content()    .delete_integration("integration-id")    .send()    .await?;

Error Handling

The SDK uses a NotraError enum with three variants:

use notra::{Notra, NotraError};match notra.content().get_post("bad-id").send().await {    Ok(response) => {        if let Some(post) = response.post {            println!("Found: {}", post.title);        }    }    Err(NotraError::Api { status, message }) => {        eprintln!("API error ({}): {}", status, message);    }    Err(NotraError::Http(e)) => eprintln!("Network error: {e}"),    Err(NotraError::Builder(msg)) => eprintln!("Config error: {msg}"),}

Types

All types are exported under notra::models:

use notra::models::{    Post, PostStatus, ContentType, Sort,    Pagination, Organization,    LookbackWindow, DataPoints, Repository,    BrandIdentity, ToneProfile, Language,    GithubIntegration, LinearIntegration,    PostGenerationJob, JobStatus,};

Hat das auf deinem Setup funktioniert?

Noch nicht bewertet