concur-api 0.1.0

A Rust client for the SAP Concur REST APIs (v4 / v4.1).
Documentation

concur-api

CI Crates.io Docs.rs License: MIT

A typed, async Rust client for the SAP Concur REST APIs. This crate targets the latest generally available v4 / v4.1 endpoints and avoids deprecated v3 APIs where a v4 successor exists.

Supported APIs

Area API Version Base path
Authentication OAuth2 / App Authorization v0 oauth2/v0/token
Identity Identity API v4.1 profile/identity/v4.1
Expense Expense Reports API v4 expensereports/v4/.../reports
Expense Expenses (entries) API v4 expensereports/v4/.../expenses
Expense Expense Workflow API v4 expensereports/v4/.../approve etc.
Configuration Lists API v4 list/v4/lists
Configuration List Items API v4 list/v4/items
Receipts Receipts API v4 receipts/v4/...
Request Travel Request API v4 travelrequest/v4/requests
Request Request Workflow API v4 travelrequest/v4/requests/{id}/{action}
Request Expected Expenses API v4 travelrequest/v4/requests/{id}/expenses
Request Request Allocations API v4 travelrequest/v4/requests/{id}/allocations
Cards Cards API v4 cards/v4/companies/{id}/accounts/bulk
Cards Card Transactions API v4 cards/v4/companies/{id}/transactions/bulk
Purchasing Purchase Request API v4 purchaserequest/v4/...
Invoice Invoice Pay API v4 invoice/provider-payment/v4/payments
Events Event Subscription Service (ESS) v4 events/v4/...

APIs intentionally excluded

The following APIs were requested but do not have a v4 endpoint (or the v4 endpoint is not publicly documented) as of the latest SAP Concur Developer Center review:

  • Expense Allocations API — only v3 exists (/api/v3.0/expense/allocations).
  • Expense Attendees API — only v1/v2/v3 exist.
  • Expense Itemizations API — only v3 exists; itemizations are exposed as links inside Expenses v4.
  • Company / Organization API — v1 is deprecated (May 2025); company context is available via Identity v4.1 user profiles.
  • General Invoice API — only v3 exists; v4 is limited to Invoice Pay and Invoice Payment Confirmation.
  • Purchase Order APIs — only v3 exists.
  • Cost Centers / Custom Fields APIs — no v4 endpoints found.

Installation

Add this to your Cargo.toml:

[dependencies]
concur-api = "0.1"

Quick start

use concur_api::{ClientConfig, ConcurClient, Result};
use concur_api::auth::{OAuth2TokenManager, Grant};
use concur_api::api::expense::ReportsApi;

#[tokio::main]
async fn main() -> Result<()> {
    let config = ClientConfig {
        base_url: "https://us.api.concursolutions.com".to_string(),
        ..Default::default()
    };

    let manager = OAuth2TokenManager::new(
        "https://us.api.concursolutions.com/oauth2/v0/token",
        "your-client-id",
        "your-client-secret",
        Grant::ClientCredentials {
            scope: Some("expense.report.read".to_string()),
        },
    );

    let client = ConcurClient::new(config)?.with_token_manager(manager);
    let reports = ReportsApi::new(&client);

    let report = reports.get(
        "32c2fcc3-b2e8-4907-9672-5b3f49b1c643",
        "TRAVELER",
        "764428DD6A664AF0BFCB",
    ).await?;

    println!("{:?}", report);
    Ok(())
}

Authentication

The crate supports multiple OAuth2 flows:

  • Grant::ClientCredentials — company / application tokens.
  • Grant::Password — user tokens (including App Center authtoken credential type).
  • Grant::RefreshToken — refresh an existing token.
  • StaticToken — for testing or when you already have a token.

Token refresh is handled automatically by OAuth2TokenManager before the token expires.

Features

  • Async/await API built on reqwest and tokio.
  • Automatic token refresh and geolocation-aware base URLs.
  • Exponential backoff retry for transient HTTP errors (429, 5xx).
  • concur-correlationid header generation for request tracing.
  • Strongly typed request/response models for all supported APIs.
  • ESS webhook subscription management.

Geolocation

SAP Concur returns a geolocation field in the OAuth2 token response. You should configure ClientConfig::base_url with that value for subsequent API calls. The client does not automatically switch data centers; store the geolocation from the token response and create a new ConcurClient for that base URL.

Rate limits and retries

The client retries idempotent GET/PUT/DELETE requests automatically on 429 / 5xx responses. Non-idempotent POST/PATCH requests are also retried, but callers should supply an idempotency key where the API supports it. Configure retry behavior via ClientConfig::max_retries and ClientConfig::retry_backoff.

Documentation

License

This project is licensed under the MIT License.

Authors