Skip to main content
Version: 1.15.2

API Overview

Welcome to the Moss API!

API Introduction

Our REST API enables you to connect Moss with your systems, and automate finance workflows. It has predictable resource-oriented URLs, accepts JSON-encoded request bodies, returns JSON-encoded responses, and uses standard HTTP response codes, authentication, and verbs.

With this API, you can:

  • Access expenses, including card transactions, invoices, and reimbursements, along with accounting attributes and dimensions
  • Retrieve user and supplier information
  • Retrieve accounting attributes and dimensions

Base URLs

All API endpoints are prefixed with /v1, for example:

https://public-api.getmoss.com/v1/expenses

API Version

The current API version is v1. The version is included in the URL path to ensure backward compatibility as the API evolves.

HTTP Methods

The API uses standard HTTP methods:

  • GET - Retrieve resources
  • POST - Create new resources (not yet supported)
  • PUT - Update existing resources (not yet supported)
  • PATCH - Partially update resources (not yet supported)

Getting Started

  1. Create API Keys: Only admins can create API keys.
  2. Obtain Access Token: Use your Key ID and Secret Key to request a Bearer token
  3. Use Access Token: Include the token in API requests via Authorization header

Create API Keys

  1. Log in to your Moss account as an admin
  2. Navigate to Settings → Company Settings → API Keys

Settings page

  1. Click "Generate API Key"
  2. Confirm the operation with Moss mobile app
  3. Save both the Key ID (kid_) and Secret Key (sk_) securely

Important: Store credentials securely and never expose them in client-side code

Authentication

Our API uses OAuth 2.0 client credentials flow to obtain Bearer tokens for authentication.

Obtain Access Token

Endpoint: POST {server_url}/oauth2/token

Request Parameters:

  • grant_type: Must be client_credentials
  • client_id: Your Key ID (starts with kid_)
  • client_secret: Your Secret Key (starts with sk_)
  • scope: Access level - read or write. Optional parameter, defaults to read

Example Request:

curl -X POST "https://public-api.getmoss.com/oauth2/token" \
-H "content-type: application/x-www-form-urlencoded" \
-d 'grant_type=client_credentials&client_id=kid_FaYnufhSMSP1qaXy&client_secret=sk_rKvWDzU6h46hiy3tluqskkrX6pepQTXI'

Response Example:

{
"access_token": "eyJhbGciOiJFUzI1NiJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "read"
}

Use Access Token

Include the access_token value in the Authorization header of your API requests:

curl -H "Authorization: Bearer eyJhbGciOiJFUzI1NiJ9..." \
https://public-api.getmoss.com/v1/expenses

Token Management

  • Token Lifetime: Access tokens expire after 1 hour (3600 seconds)
  • Token Refresh: Since this is client credentials flow, request a new token when the current one expires
  • Token Format: JWT (JSON Web Token) with embedded user and scope information

Scopes and Permissions

  • read: Grants access to GET endpoints for retrieving data
  • write: Grants access to all endpoints including POST, PUT, DELETE operations
  • Scope Hierarchy: write scope includes read permissions

Security Best Practices

  • Rotate API keys regularly
  • Use environment variables to store credentials
  • Never commit API keys to version control
  • Never expose credentials in client-side code
  • Monitor API key usage for suspicious activity

Rate Limiting

API requests are rate limited to ensure service reliability and fair usage across all clients.

Every API response includes the following rate limiting headers:

HeaderDescription
X-RateLimit-LimitMaximum requests allowed in the current rate limit window
X-RateLimit-RemainingRequests remaining in the current window
X-RateLimit-ResetUnix timestamp (UTC seconds) when the window resets
X-RateLimit-ScopeScope bucket for this limit: read or write

When the rate limit is exceeded the API returns HTTP 429 Too Many Requests with:

  • All four X-RateLimit-* headers (X-RateLimit-Remaining will be 0)
  • Retry-After header with the number of seconds to wait before retrying
  • A JSON error body with type: ERR_RATE_LIMIT_EXCEEDED

Rate Limiting Best Practices

  • Monitor X-RateLimit-Remaining to avoid hitting the limit
  • Implement exponential backoff when receiving 429 responses
  • Respect the Retry-After header value when retrying

Pagination

List endpoints support pagination to manage large datasets efficiently. Currently, the API supports offset-based pagination.

Offset-Based Pagination

Some endpoints support traditional offset-based pagination.

Request Parameters:

  • page (optional): Page number (1-based, default: 1)
  • page_size (optional): Number of items per page

Example Request:

GET /v1/expenses?page=2&page_size=50

Response Format:

{
"data": [...],
"meta": {
"type": "offset",
"page": 2,
"pageSize": 50,
"hasMore": true,
"totalPages": 16,
"totalItems": 789
}
}

Pagination Fields:

  • type: Always "offset" for offset-based pagination
  • page: Current page number (1-based)
  • pageSize: Number of items per page
  • hasMore: Whether there are more pages available
  • totalPages: Total number of pages (optional)
  • totalItems: Total number of items across all pages (optional)

Errors

The API uses standard HTTP status codes and returns detailed error information based on RFC 9457 Problem Details format.

Response Structure

All responses follow a consistent structure with data, meta, and errors fields:

Success Response:

{
"data": { ... },
"meta": { ... }
}

Error Response:

{
"data": null,
"meta": {},
"errors": [
{
"type": "ERR_VALIDATION_FAILED",
"title": "Validation failed for property 'currency'",
"detail": "Validation failed for property 'currency': should be one of EUR, USD, GBP, CHF, PLN, SEK. Provided: CZK",
"pointer": "#/currency",
"status": 400,
"instance": "/v1/expenses"
}
]
}

Error Fields

  • type: Error type identifier (e.g., ERR_VALIDATION_FAILED)
  • title: Short, human-readable summary of the error
  • detail: Detailed explanation of the error
  • pointer: JSON pointer (RFC 6901) to the field that caused the error (optional)
  • status: HTTP status code (optional)
  • instance: URI reference for this specific error occurrence (optional)

HTTP Status Codes

The API uses the following HTTP status codes:

Success Codes:

  • 200 OK - Request succeeded
  • 201 Created - Resource created successfully
  • 204 No Content - Request succeeded with no response body

Client Error Codes:

  • 400 Bad Request - Invalid request parameters or body
  • 401 Unauthorized - Missing or invalid authentication token
  • 403 Forbidden - Authenticated but not authorized to access the resource
  • 404 Not Found - Resource not found
  • 422 Unprocessable Entity - Request validation failed
  • 429 Too Many Requests - Rate limit exceeded

Server Error Codes:

  • 500 Internal Server Error - An error occurred on the server
  • 503 Service Unavailable - Service temporarily unavailable

Common Error Types

  • ERR_VALIDATION_FAILED - Request validation failed
  • ERR_UNAUTHORIZED - Authentication required or failed
  • ERR_FORBIDDEN - Insufficient permissions
  • ERR_NOT_FOUND - Resource not found
  • ERR_RATE_LIMIT_EXCEEDED - Too many requests