Authenticate with OAuth2, upload a PDF with reqwest multipart, send it for signing, and verify webhook signatures with HMAC-SHA256. No SDK — just reqwest + tokio.
reqwest is the standard choice. Use version 0.12+ with the "json" and "multipart" features enabled in Cargo.toml. reqwest builds on tokio's async runtime, handles bearer auth via .bearer_auth(), and serializes multipart form data cleanly — the three things you need for the GetSigned integration. If you're on a synchronous runtime, reqwest also has a blocking module.
Use reqwest::multipart::Form with a Part built from the file's bytes: multipart::Part::bytes(file_bytes).file_name("filename.pdf").mime_str("application/pdf"). The signers and fields are added as text parts with JSON string values. The Content-Type: multipart/form-data header is set automatically by reqwest when you call .multipart(form) on the request builder.
Use the hmac crate with sha2: add hmac = { version = "0.12", features = ["std"] } and sha2 = "0.10" to Cargo.toml, plus hex for encoding. Create an Hmac<Sha256> from your webhook secret, call .update() with the raw request body bytes, finalize and hex-encode, then compare to the x-getsigned-signature header. Read the raw body bytes BEFORE any JSON deserialization — parsing the body first can alter whitespace and invalidate the signature.
Yes. Access tokens expire (typically 1 hour). Cache the token in an Arc<Mutex<Option<(String, Instant)>>> and re-fetch when it's within 60 seconds of expiry. This avoids a token round-trip on every API call. For multi-threaded Axum servers, share the cache via Axum's State extractor so all handler tasks use the same cached token.
Yes. The webhook handler example above uses Axum, which pairs naturally with reqwest (both are tokio-based). For Actix-web, replace axum::extract::* with actix-web::web::* equivalents — the HMAC verification logic is identical. The key constraint for either framework: extract the raw body bytes as Bytes before JSON parsing, so the HMAC is computed over the original payload.
Related: Go how-to · Webhook guide · Language-agnostic guide