Everything an AI agent can do with the Spendesk API.

A reference guide for building AI agents: every method, how to authenticate, and the permissions each one needs.

Endpoints33
API versionv1
Last updated23 June 2026
Orientation

How the Spendesk API works.

The Spendesk API is how an app or AI agent works with a company's spend data: reading settlements and payables, pulling the receipts attached to an expense, and listing suppliers, members, and cost centers. Access is granted through credentials that are exchanged for a bearer token, and that token carries only the scopes chosen when the credentials were created, so an agent reaches just the kinds of spend data it was granted. The API is read-first, and Spendesk also runs a hosted server that exposes read access to agents and can push events when a payable or settlement is created.

33Endpoints
8Capability groups
21Read
12Write
18Permissions
Authentication
Every call needs a bearer access token, sent as 'Authorization: Bearer '. A company's Account Owner creates Public API credentials, a client ID and secret, in Settings, then exchanges them for a token by sending the ID and secret base64-encoded with the Basic prefix. Partners building an integration use OAuth 2.0 with PKCE to obtain a token on behalf of a connected company. Credentials are available on Premium and Enterprise plans and expire within a year.
Permissions
Access is set by scopes chosen when the credentials are created, and the token carries only those scopes. Each data type has its own read scope, such as settlement:read, payable:read, payable-attachment:read, supplier:read, user:read, cost-center:read, bank-fee:read, wallet-load:read, wallet-summary:read, analytical-field:read, and expense-category:read. Receipts sit behind their own payable-attachment:read scope, separate from payable:read. A few areas add a write or manage scope, like cost-center:manage, and the newer write areas, including suppliers, purchase orders, accounting export, and webhooks, are prefixed experimental.
Read-first
The API is built mainly for reading spend data out of Spendesk, not changing it. Settlements, payables, receipts, bank fees, wallet loads, members, suppliers, cost centers, analytical fields, and expense categories are all read-only. Writes exist only in a handful of areas, like creating cost centers and suppliers, raising purchase orders, and registering webhooks, and several of those are marked experimental.
Data model
The API answers at https://public-api.spendesk.com under the v1 path, with a sandbox at https://public-api.demo.spendesk.com. Data is scoped to one company, called the entity. A payable is one expense, whether a card purchase, an invoice, or an expense claim; a settlement records money leaving the wallet. Large payable extracts are pulled through an asynchronous snapshot, which is requested, then polled by key until complete. A hosted MCP server and signed webhooks complement the REST API.
Connect & authenticate

Connection & authentication methods.

How an app or AI agent connects to Spendesk determines what it can reach. There is a route for making calls, a route for receiving events, and a hosted server that exposes Spendesk to agents, and each is governed by the credentials behind it and the scopes those credentials carry.

Ways to connect

REST API

The REST API answers at https://public-api.spendesk.com under the v1 path, with a separate sandbox at https://public-api.demo.spendesk.com. It is read-first: most resources are read-only, and a few areas, like suppliers, cost centers, and purchase orders, also allow writes.

Best forConnecting an app or AI agent to Spendesk.
Governed byThe access token and the scopes the credentials carry.
Docs ↗

MCP server (Spendesk AI Connect)

Spendesk hosts its own Model Context Protocol server at https://public-api.spendesk.com/v1/mcp, marketed as Spendesk AI Connect. It is read-only, lets an agent query spend data, payables, suppliers, purchase orders, cost centers, and settlements in plain language, and is in beta with general availability planned. It authorizes through the same scoped credentials as the REST API.

Best forConnecting an AI agent to Spendesk for read-only queries.
Governed byThe access token and the read scopes the credentials carry.
Docs ↗

Webhooks

Webhooks deliver the chosen events to a receiver URL the company registers, signed with a secret so the receiver can confirm the payload came from Spendesk. The events cover payables being created or prepared and settlements being created. This area is marked experimental.

Best forConnecting an app or AI agent to Spendesk.
Governed byThe access token and the experimental:webhooks scopes the credentials carry.
Docs ↗
Authentication

Public API credentials (API key)

A company's Account Owner creates a client ID and secret in Settings, picks the scopes it carries, and sets an expiry of up to one year. The credentials are exchanged for a bearer access token at the token endpoint, sending the ID and secret base64-encoded with the Basic prefix. Available on Premium and Enterprise plans.

TokenBearer access token from client ID and secret
Best forA company calling its own Spendesk data
Docs ↗

OAuth 2.0 (partner apps)

A partner building an integration runs an authorization-code flow with PKCE: a connected company signs in and grants the chosen scopes, and the resulting code is exchanged for a bearer access token. The token acts on behalf of that company, limited to the scopes it granted.

TokenBearer access token via authorization code with PKCE
Best forA partner acting on behalf of connected companies
Docs ↗
Capability map

What an AI agent can do in Spendesk.

The Spendesk API is split into areas an agent can act on, like settlements, payables, suppliers, members, and cost centers. Most areas are read-only, and the scope chosen when credentials are created decides which areas a given agent can reach at all.

Spend data

8 endpoints

Read settlements, payables and their receipts, request asynchronous payable snapshots, and read bank fees, wallet loads, and the wallet summary.

Payables and settlements expose what a company spent and on what.
View endpoints

Suppliers & members

6 endpoints

List and read suppliers, list and read the members (users) of a company, create and update suppliers, and archive them.

Members include people's names and email addresses; supplier writes change vendor records.
View endpoints

Analytical & cost centers

7 endpoints

Read analytical fields and their values, read expense categories, and read, create, update, or delete cost centers.

Cost center writes change how spend is categorized across the company.
View endpoints

Purchase orders

3 endpoints

List and read purchase orders, create a purchase order, and cancel or close one.

This area is experimental and writes commit real purchase commitments.
View endpoints

Accounting export

2 endpoints

Read journal templates, create an accounting export, read a journal's content, and check the export status of entities.

This area is experimental and exposes full accounting journals.
View endpoints

Authentication

3 endpoints

Exchange Public API credentials for an access token, or run the partner authorization flow to obtain a token on behalf of a connected company.

These mint the bearer token every other call depends on.
View endpoints

Webhooks

3 endpoints

Create, list, read, update, and delete webhook instances that subscribe to payable and settlement events.

This area is experimental and registers where event payloads are sent.
View endpoints

MCP server

1 endpoint

The hosted Model Context Protocol endpoint that exposes read access to spend data, suppliers, members, and cost centers to an AI agent.

Read-only, and limited to the scopes the connecting credentials carry.
View endpoints
Endpoint reference

Every Spendesk API method.

Filter by method, access, or permission, or search any path. Select a row for version detail, rate limits, the related webhook event, and the source.

MethodEndpointWhat it doesAccessPermissionVersion

Spend data

Read settlements, payables and their receipts, request asynchronous payable snapshots, and read bank fees, wallet loads, and the wallet summary.8

The bearer token must carry the settlement:read scope, chosen when the credentials were created. Settlement data is served from a cache, so a response can be up to 86,400 seconds old.

Acts onsettlement
Permission (capability)settlement:read
VersionAvailable since the API’s base version
Webhook eventsettlements-created
Rate limitStandard limits apply

Requires the payable:read scope. Payable data is served from a cache, so a response can be up to 1,200 seconds old.

Acts onpayable
Permission (capability)payable:read
VersionAvailable since the API’s base version
Webhook eventpayables-created
Rate limitStandard limits apply

Requires the payable:read scope. This is the supported way to list many payables, since the synchronous list was removed at general availability. Snapshot requests must be made one at a time, not in parallel.

Acts onpayable snapshot
Permission (capability)payable:read
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Requires the payable:read scope. The snapshot is built asynchronously, so this is polled until its status is COMPLETE.

Acts onpayable snapshot
Permission (capability)payable:read
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Requires the payable-attachment:read scope, which is separate from payable:read because attachments hold receipt images. The download URLs expire, and the response is cached for up to 3,300 seconds.

Acts onpayable attachment
Permission (capability)payable-attachment:read
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Requires the bank-fee:read scope. Bank fee data is served from a cache, so a response can be up to 86,400 seconds old.

Acts onbank fee
Permission (capability)bank-fee:read
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Requires the wallet-load:read scope. Wallet load data is served from a cache, so a response can be up to 86,400 seconds old.

Acts onwallet load
Permission (capability)wallet-load:read
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Requires the wallet-summary:read scope. The summary is served from a cache, so a response can be up to 86,400 seconds old.

Acts onwallet summary
Permission (capability)wallet-summary:read
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Suppliers & members

List and read suppliers, list and read the members (users) of a company, create and update suppliers, and archive them.6

Requires the supplier:read scope. Supplier data is served from a cache, so a response can be up to 604,800 seconds old.

Acts onsupplier
Permission (capability)supplier:read
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Requires the supplier:read scope.

Acts onsupplier
Permission (capability)supplier:read
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Requires the experimental:supplier:manage scope. This write area is marked experimental and can change before it settles.

Acts onsupplier
Permission (capability)supplier:manage
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Requires the experimental:supplier:manage scope. This write area is marked experimental and can change before it settles.

Acts onsupplier
Permission (capability)supplier:manage
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Requires the user:read scope. This returns people's names and email addresses. User data is served from a cache, so a response can be up to 1,200 seconds old.

Acts onmember
Permission (capability)user:read
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Requires the user:read scope, which returns a person's name and email address.

Acts onmember
Permission (capability)user:read
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Analytical & cost centers

Read analytical fields and their values, read expense categories, and read, create, update, or delete cost centers.7

Requires the analytical-field:read scope. The data is served from a cache, so a response can be up to 604,800 seconds old.

Acts onanalytical field
Permission (capability)analytical-field:read
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Requires the analytical-field:read scope.

Acts onanalytical value
Permission (capability)analytical-field:read
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Requires the cost-center:read scope. Cost center data is served from a cache, so a response can be up to 86,400 seconds old.

Acts oncost center
Permission (capability)cost-center:read
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Requires the cost-center:manage scope, which is separate from the read scope.

Acts oncost center
Permission (capability)cost-center:manage
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Requires the cost-center:manage scope.

Acts oncost center
Permission (capability)cost-center:manage
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Requires the cost-center:manage scope.

Acts oncost center
Permission (capability)cost-center:manage
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Requires the expense-category:read scope. The data is served from a cache, so a response can be up to 86,400 seconds old.

Acts onexpense category
Permission (capability)expense-category:read
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Purchase orders

List and read purchase orders, create a purchase order, and cancel or close one.3

Requires the experimental:purchase-order:read scope. This area is marked experimental and can change before it settles.

Acts onpurchase order
Permission (capability)purchase-order:read
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Requires the experimental:purchase-order:write scope. This area is marked experimental and can change before it settles.

Acts onpurchase order
Permission (capability)purchase-order:write
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Requires the experimental:purchase-order:write scope. This area is marked experimental and can change before it settles.

Acts onpurchase order
Permission (capability)purchase-order:write
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Accounting export

Read journal templates, create an accounting export, read a journal's content, and check the export status of entities.2

Requires the experimental:accounting-export:read scope, the single scope that covers this whole experimental area. This area is marked experimental and can change before it settles.

Acts onaccounting export
Permission (capability)accounting-export:read
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Requires the experimental:accounting-export:read scope. This area is marked experimental and can change before it settles.

Acts onjournal
Permission (capability)accounting-export:read
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Authentication

Exchange Public API credentials for an access token, or run the partner authorization flow to obtain a token on behalf of a connected company.3

No scope is needed to call this, but the token it returns carries only the scopes chosen when the credentials were created. This is the server-to-server flow for a company's own credentials, not the partner OAuth flow.

Acts onaccess token
Permission (capability)None required
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Used by partner apps acting on behalf of a connected company, not by a company calling its own data. The returned code is exchanged for a token at the OAuth2 token endpoint.

Acts onauthorization
Permission (capability)None required
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

The returned token carries the scopes the connected company granted during authorization.

Acts onaccess token
Permission (capability)None required
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Webhooks

Create, list, read, update, and delete webhook instances that subscribe to payable and settlement events.3

Requires the experimental:webhooks:write scope. This area is marked experimental and can change before it settles.

Acts onwebhook
Permission (capability)webhooks:write
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Requires the experimental:webhooks:read scope. This area is marked experimental and can change before it settles.

Acts onwebhook
Permission (capability)webhooks:read
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Requires the experimental:webhooks:write scope. This area is marked experimental and can change before it settles.

Acts onwebhook
Permission (capability)webhooks:write
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

MCP server

The hosted Model Context Protocol endpoint that exposes read access to spend data, suppliers, members, and cost centers to an AI agent.1

Read-only. The connecting credentials decide which areas the agent can reach, through the same read scopes the rest of the API uses, such as settlement:read and payable:read. Marketed as Spendesk AI Connect and in beta.

Acts onMCP session
Permission (capability)None required
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply
No endpoints match those filters.
Webhooks

Webhook events.

Spendesk can notify an app or AI agent when something happens in a company, like a payable being created or a settlement being recorded, instead of the app repeatedly asking. Spendesk posts a signed payload to a webhook URL that has been registered for the chosen events.

EventWhat it signalsTriggered by
payables.createdFires when a payable is created, at version 1. A payable is one expense, such as a card purchase, an invoice, or an expense claim./v1/payables/{id}
payables.preparedFires when a payable is prepared, the step where it is enriched and made ready for accounting.In-app only
settlements.createdFires when a settlement is created, at version 1. A settlement records money moving out of the company's Spendesk wallet./v1/settlements
No events match that search.
Rate limits & pagination

Rate limits, pagination & request size.

Spendesk limits how fast an app or AI agent can call, through a per-minute request quota measured per company and a separate cap on how many requests run at once. Most responses are also served from a cache, so repeated reads return data that can be up to a set number of seconds old.

Request rate

Spendesk limits requests per minute per company. A company calling its own data, and a partner calling on behalf of one connected company, each get 50 requests per minute; a partner using OAuth 2.0 gets 250 requests per minute. On top of that, any caller is held to 5 requests running at once. Every response carries x-ratelimit-limit, x-ratelimit-remaining, and x-ratelimit-reset headers, and exceeding a limit returns 429 until the number of seconds in x-ratelimit-reset has passed. Most read endpoints are also served from a cache, so repeated reads can return data up to a fixed age, which ranges from 1,200 seconds for payables and members to 604,800 seconds for suppliers and analytical fields.

Pagination

List endpoints use page-based pagination through the page parameter, which starts at 1, and the pageSize parameter, which defaults to 30 and tops out at 30. Asking for a page past the last one with results returns a 404 rather than an empty list. Listing many payables is done through the asynchronous snapshot endpoints rather than a direct list.

Request size

Responses are JSON, except the accounting journal endpoint, which returns CSV. Payable date-range queries are capped at a 31-day window between the from and to dates. A company can configure at most 50 webhook instances, and a webhook signing secret must be at least 32 characters.

Errors

Status codes & error handling.

The status codes an agent should handle, and what to do about each.

StatusCodeMeaningWhat to do
400BAD_REQUEST_INCORRECT_OR_MISSING_FIELDThe request was malformed, or a required field was missing or invalid.Read the detail in the errors array, correct the named field, and resend.
401AUTHENTICATION_ERRORAuthentication is missing, or the access token is invalid or expired.Request a fresh access token from the token endpoint and retry with it in the Authorization header.
403FORBIDDEN_ERRORThe token is valid but does not carry the scope the endpoint requires.Issue credentials that include the needed scope, such as settlement:read, then mint a new token.
404NOT_FOUNDThe resource does not exist, or a paginated request asked for a page beyond the last one with results.Confirm the ID, and stop paging when a 404 is returned for the next page.
409CONFLICT_ERRORThe request conflicts with the current state, such as creating something that already exists.Refetch the current state, then retry once the conflict is resolved.
422IN_PROGRESSAn asynchronous request, such as a payable snapshot, is still being built and is not ready to read.Wait, then poll the snapshot again until its status is COMPLETE.
429TOO_MANY_REQUESTSA rate limit was exceeded, either the per-minute quota or the cap on requests running at once.Wait for the number of seconds in the x-ratelimit-reset header before retrying.
500INTERNAL_SERVER_ERRORSomething failed on Spendesk's side while handling the request.Retry after a short delay, and contact Spendesk if it persists.
Versioning & freshness

Version history.

Spendesk versions its API through a single path segment, v1, and ships dated changes through release notes. The current generation reached general availability in 2024, when the earlier v0 generation was switched off.

Version history

What changed, and when

Latest versionv1
v1Current version
General availability of the v1 API

The v1 generation is the current, supported API. It reached general availability in 2024, when it replaced the earlier v0 generation, which stopped working on 29 April 2024. At that point the synchronous payables list was removed in favour of the asynchronous payable snapshot, payable date-range queries were capped at a 31-day window, and the maximum page size across all endpoints was reduced to 30. Newer areas, like suppliers writes, purchase orders, accounting export, and webhooks, ship under an experimental prefix and can change before they settle.

What changed
  • Removed the synchronous payables list in favour of the asynchronous payable snapshot
  • Capped payable date-range queries at a 31-day window
  • Reduced the maximum page size across all endpoints to 30
  • v0 endpoints stopped working on 29 April 2024
Later additions
Webhooks, accounting exports, and the MCP server

After general availability, Spendesk added experimental webhooks for payable and settlement events, APIs for accounting exports, and later a hosted Model Context Protocol server, Spendesk AI Connect, that exposes read access to spend data to AI assistants. These build on v1 without minting a new version string, and several remain marked experimental.

What changed
  • Added experimental webhooks for payable and settlement events
  • Added APIs for accounting exports
  • Added the hosted Spendesk AI Connect MCP server, read-only and in beta
v0
Original API generation (retired)

The v0 generation was the first public API. It carried breaking changes in March 2024 and was switched off entirely on 29 April 2024, after which every call had to move to the v1 path.

What changed
  • Breaking changes announced for 14 March 2024
  • All v0 endpoints retired on 29 April 2024

Newer areas are marked experimental and can change before they settle.

Spendesk API changelog ↗
Questions

Spendesk API, answered.

Is the Spendesk API authenticated with a static API key, or with OAuth?+
Both, depending on who is calling. A company calling its own data creates Public API credentials, a client ID and secret, and exchanges them for a short-lived bearer token, which is the API-key style flow. A partner building an integration for other companies uses OAuth 2.0 with PKCE, where each connected company signs in and grants scopes. Either way, every call carries a bearer token, and the scopes on that token decide what it can read.
How do scopes work, and what does each one cover?+
When credentials are created, the owner picks the scopes they carry, and the token can never reach beyond them. Each data type has its own read scope, like settlement:read or supplier:read, so an integration can be limited to exactly the kinds of spend data it needs. Receipts have a separate payable-attachment:read scope because they hold receipt images. A few areas add a manage or write scope for changes, and the newer write areas are prefixed experimental, which signals they can still change.
Why is there no plain 'list all payables' endpoint?+
Listing many payables is done through an asynchronous snapshot rather than a direct list, a change made when the API reached general availability. A POST request queues a snapshot and returns a key right away, then the snapshot is polled by that key until its status is COMPLETE, at which point the payables are returned. Snapshots must be requested one at a time, and a payable date range is capped at a 31-day window.
What are the rate limits?+
A company, or a partner calling for one connected company, gets 50 requests per minute, while an OAuth 2.0 partner gets 250 per minute, and any caller is also held to 5 requests at once. Each response carries x-ratelimit-limit, x-ratelimit-remaining, and x-ratelimit-reset headers, and going over returns 429 until the seconds in x-ratelimit-reset have passed. Many reads are also cached, so a repeated read can return data that is a fixed number of seconds old.
Does Spendesk have an MCP server for AI agents?+
Yes. Spendesk hosts its own Model Context Protocol server, marketed as Spendesk AI Connect, that lets an AI assistant query spend data, payables, suppliers, purchase orders, cost centers, and settlements in plain language. It is read-only and cannot create payments, approve invoices, or change records, and it authorizes through the same scoped credentials as the REST API. It is in beta, with general availability planned.
How do I receive events instead of polling?+
Webhooks deliver events without polling, though this area is marked experimental. A receiver URL and a signing secret are registered for the chosen events, which cover a payable being created or prepared and a settlement being created. Spendesk posts a signed payload when each event fires, and a company can configure up to 50 webhook instances.
Related

More finance API guides for agents

What is Bollard AI?

Control what every AI agent can do in Spendesk.

Bollard AI sits between a team's AI agents and Spendesk. Grant each agent exactly the access it needs, read or write, resource by resource, and every call is checked and logged.

  • Set read, write, or full access per agent, never a shared Spendesk key.
  • Denied by default, so an agent reaches only what has been explicitly allowed.
  • Every call recorded in plain English: who, what, where, and the decision.
Spendesk
Finance Agent
Read settlements ResourceOffReadFull use
Read payables and receipts ResourceOffReadFull use
Suppliers ResourceOffReadFull use
Cost centers ResourceOffReadFull use
Per-agent access, set in Bollard AI, not in Spendesk