Rust
Dependencias
# Cargo.toml
[dependencies]
reqwest = { version = "0.12", features = ["json"] }
tokio = { version = "1", features = ["full"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
Local file
use reqwest::Client;
use std::fs;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new();
let pdf = fs::read("report.pdf")?;
let res = client
.post("https://api.markpdf.tech/convert/raw")
.query(&[("filename", "report.pdf"), ("mode", "fast")])
.header("x-api-key", "YOUR_API_KEY")
.header("content-type", "application/pdf")
.body(pdf)
.send()
.await?;
let markdown = res.text().await?;
println!("{markdown}");
Ok(())
}
URL signed
use reqwest::Client;
use serde_json::json;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new();
let res = client
.post("https://api.markpdf.tech/convert/from-url")
.header("x-api-key", "YOUR_API_KEY")
.json(&json!({
"url": "https://bucket.s3.amazonaws.com/report.pdf?X-Amz-Signature=...",
"filename": "report.pdf",
"mode": "fast"
}))
.send()
.await?;
println!("{}", res.text().await?);
Ok(())
}
Handling of 202 (auto-async)
When all backends are saturated, API returns202. Poll /jobs/{id} until you get the result:
use reqwest::Client;
use serde::Deserialize;
use std::fs;
use tokio::time::{sleep, Duration};
const API_URL: &str = "https://api.markpdf.tech";
const API_KEY: &str = "YOUR_API_KEY";
#[derive(Deserialize)]
struct AcceptedJob {
job_id: String,
retry_after_seconds: Option<u64>,
}
#[derive(Deserialize)]
struct JobStatus {
status: String,
body: Option<String>,
error: Option<String>,
}
async fn convert(client: &Client, pdf: Vec<u8>, filename: &str) -> Result<String, Box<dyn std::error::Error>> {
let res = client
.post(format!("{API_URL}/convert/raw"))
.query(&[("filename", filename), ("mode", "fast")])
.header("x-api-key", API_KEY)
.header("content-type", "application/pdf")
.body(pdf)
.send()
.await?;
match res.status().as_u16() {
200 => Ok(res.text().await?),
202 => {
let job: AcceptedJob = res.json().await?;
let delay = Duration::from_secs(job.retry_after_seconds.unwrap_or(5));
loop {
sleep(delay).await;
let poll = client
.get(format!("{API_URL}/jobs/{}", job.job_id))
.header("x-api-key", API_KEY)
.send()
.await?
.json::<JobStatus>()
.await?;
match poll.status.as_str() {
"completed" => return Ok(poll.body.unwrap_or_default()),
"failed" => return Err(poll.error.unwrap_or("unknown".into()).into()),
_ => continue,
}
}
}
code => Err(format!("HTTP {code}: {}", res.text().await?).into()),
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new();
let pdf = fs::read("report.pdf")?;
let markdown = convert(&client, pdf, "report.pdf").await?;
println!("{markdown}");
Ok(())
}
