Working with Expenses

📒 Table of contents


In this guide, you will learn:

  • Possible operations that can be performed on an expense
  • Meaning of the response fields

Before you get started

The Remote API has the capability to create already approved expenses, to update pending expenses to approve or decline them, and to show and list expenses. Each expense belongs to an employment, has an amount in a given currency, the date it was incurred, and a receipt file.

Before you get started, you’ll need to ensure that you know the employment_id.

Creating an Expense

When creating an expense in a different currency of the employment, for instance, a €100.00 expense that belongs to an American employment, it is possible to send the following request:

1curl --location --request POST '' \
2--header 'Authorization: Bearer <your token>' \
3--header 'Content-Type: application/json' \
4--data-raw '{
5 "employment_id": "7db936d5-ea9b-4e97-a1f3-4d94ca39c294",
6 "amount": 10000,
7 "category": "education_training",
8 "currency": "EUR",
9 "expense_date": "2023-01-10",
10 "receipt": {
11 "content": "UGVyaW9kI...DAsMCwwLDEwMCwwCg==",
12 "name": "receipt.pdf"
13 },
14 "tax_amount": 0,
15 "timezone": "Etc/UTC",
16 "title": "Giving Constructive Feedback Training",
17 "reviewed_at": "2023-02-10T00:00:00Z"


The receipt field represents the receipt of the purchase, which is required to create an expense. The file name and the content encoded in base64 define a receipt to be attached to the expense. The receipt is necessary to create an expense.

To get the base64-encoded file content via the command line, you can run:

1$ base64 -i path/to/file.pdf

The response will look like this:

2 "data": {
3 "expense": {
4 "amount": 10000,
5 "category": "education_training",
6 "converted_amount": 10735,
7 "converted_currency": {
8 "code": "USD",
9 "name": "United States Dollar",
10 "symbol": "$"
11 },
12 "converted_tax_amount": 0,
13 "currency": {
14 "code": "EUR",
15 "name": "European Euro",
16 "symbol": "€"
17 },
18 "employment_id": "7db936d5-ea9b-4e97-a1f3-4d94ca39c294",
19 "expense_date": "2023-01-10",
20 "id": "c26257a7-1cb5-4cd1-bf76-3ed0a389979c",
21 "invoice_period": null,
22 "notes": null,
23 "reason": null,
24 "reviewed_at": "2023-02-10",
25 "reviewer": {
26 "user_email": "",
27 "user_id": "2f73619f-4970-4c23-a7bb-3d110a7e6cf2",
28 "user_name": "Jane Smith"
29 },
30 "status": "approved",
31 "tax_amount": 0,
32 "title": "Giving Constructive Feedback Training 5"
33 }
34 }

In this example, we created an expense with the source currency in EUR but the amount was converted to USD, since it is an American worker. If the expense is in the same currency as the country the employment was created, the amount will be the same.

Response Fields

As shown, the response object contains some fields that weren't explicitly required in the creation. Next, they're presented in more detail.


To create an expense, the request parameters must have the cost in the currency that the expense was paid. That can also be referred to as the source currency.

The response object for the create, show, and list expenses requests, returns the amount and currency of the expense in both source currency (amount and currency fields) and in the converted currency (converted_amount and converted_currency fields), which is the currency the employee or contractor will be paid in. The same definitions apply to the tax fields (tax_amount and converted_tax_amount).


The reviewer_id and reviewed_at fields are optional when creating an expense. If the approver of the expense is a user in Remote, it is possible to provide the user_id for the reviewer_id field. If the value is not provided, it will default to the user that generated the API access token. The same applies to the reviewed_at field. If the timestamp is not provided, it will be set to the timestamp of when the request was done.

To search for possible user_ids to set the reviewers, query the /company-managers endpoint.

You can check the documentation for it here.

Approving or Declining an Expense

You can approve or decline a pending expense using the PUT /expenses/:id or PATCH /expenses/:id endpoints. The :id in the query parameter must be replaced with the ID of the expense to be updated.

To approve an expense, simply update its status to approved. Conversely, to decline an expense, update its status to declined and provide a reason for declination:

2 "status": "declined",
3 "reason": "Expense not refundable"

Fetching the receipt file

As mentioned, a receipt is a required parameter to create an expense. To retrieve the file sent when creating the expense, send a request to the GET /expenses/:id/receipt endpoint. The :id in the query parameter must be a valid expense ID, which you can obtain from the List Expenses endpoint, for example. Here's an example of how to fetch the receipt file:

1$ curl --location --request POST '' \
2--header 'Authorization: Bearer <your token>' \
3--header 'Content-Type: application/json'
5$ // receipt.pdf binary file content

Getting notified on events

You can receive notifications for changes in expenses by subscribing to the following events:

  • expense.submitted , triggered when an approved expense is submitted to Remote;
  • expense.updated , triggered for any modification of an expense, except when it is deleted;
  • expense.deleted , triggered when an expense is deleted by an employee.

It is important to note that when an employee modifies a declined expense, it will be moved back to the pending status and then both expense.submitted and expense.updated events will be triggered.

Please refer to the API Reference documentation to obtain the most up-to-date information about the data sent and available events. Additionally, check the Working with Webhooks Guide to learn how to register and test webhooks.

Other operations

There's also the GET /expenses endpoint, to query the list of expenses of all employments that belong to the company, and the GET /expenses/:id endpoint, to show information of a single expense. Some other operations involving expense reimbursement request that has not been approved, are not yet supported. However, please contact Remote at if you need a feature that is not available.