Overview
Environments
Environment | Base URL |
---|---|
Production | https://api.jenji.io |
Unstable | https://api-test.jenji.io |
Authentication
The Jenji API uses HTTP Basic Authentication.
Using an organisation API Key
curl -X GET "https://api-test.jenji.io/s/test" \
-u API_USER_ID:SECRET_KEY
With every request made to the API you must provide your API user ID and key as basic auth credentials.
Using a bookkeeper API Key
curl -X GET "https://api-test.jenji.io/s/test" \
-u API_USER_ID:SECRET_KEY:API_BK
With every request made to the API you must provide your API user ID, secret key and key type as basic auth credentials.
Rate limits
We have a rate limit in place in order to provide a fair response time to all our API users.
API calls will be rate limited after 3 requests per second or 120 requests per minutes, whichever happens first. All requests count towards the rate limit.
Data model
The data model of Jenji is articulated around two major domains of expense management:
- the organization domain, for the operational part (creating, validating expenses)
- the bookkeeper domain, for the accounting firm part (managing organizations and their data)
Both domains may interact together, for instance when an organization delegates the accounting of its expenses to a bookkeeper.
Organization Domain
An organization
is an operating company, for which we want to track expenses
. It is structured into a hierarchy of organization groups
,
each group representing an operational team of the company. The top group of the hierarchy is the default system root group
.
Members of the organization, such as sales representatives and managers, may gain access to the organization as organization users
, to act at the
many steps of the workflow of expense management. They belong to a particular group, thus inheriting security and access policies defined for that group.
Some members may create expenses
to record their spending and request reimbursement. Expenses may be of different types:
- standard expenses, with a
receipt
scanned and uploaded to Jenji mileage
expenses, for travels with a personal vehicleallowance
expenses, whereby users may spend up to a certain amount for a fixed reimbursable activity
Expenses may also be grouped together in an expense request
(if the option has been enabled), allowing for a more old school validation workflow.
The expense, aside from its various header data and amounts, is also enriched with analytic data, which can be customized per organization and per group.
Standard analytic data include a category
, such as "meal" or "travel", a payment method
which was used to pay for the expense (like a credit card),
or even a vehicle
in case of mileage expenses.
Organization may also define their own analytic drivers, with custom fields
, which form a powerful way to mark an expense for accurate accounting repartition.
Custom fields may be of different types
, for instance numbers, lists, dates or places,
and be made available to the end users depending on scoping conditions
: expenses, expense requests, users, groups and advances.
Finally, the process of expense management
may be standard, with simple phases of expense creation, checking, validation, accounting and reimbursement, or be
completely customized for an organization, with a dedicated workflow
and user profiles
authorized to act on specific steps of that workflow.
Bookkeeper Domain
A bookkeeper
is an accounting company, which manages the accounts of client companies, such as liberal professionals.
Like an organization, a bookkeeper is structured into a hierarchy of bookkeeper groups
topped by a default system root group
,
each group representing an operational team of the bookkeeper.
Team members, a.k.a. bookkeeper users
, belong to only one group, inheriting security and access policies defined for that group.
An organization may delegate the accounting of its expenses to a bookkeeper,
in which case it becomes a client
(or account
) of that bookkeeper.
In particular cases, bookkeepers may also delegate part of their activity to another bookkeeper,
which then becomes their master bookkeeper
.
Support
You can contact us at support-api@jenji.io.
Organizations
Set of methods to create, update or view organizations. These methods may only be used by an organization, by its bookkeeper or by the master bookkeeper of its bookkeeper.
List available organization summaries
curl -X GET "https://api-test.jenji.io/api/org/v1/organizations" \
-u API_USER_ID:SECRET_KEY \
{
"data" : [ {
"id" : "74dbaf20-7f22-45e6-8378-cf33cb775687",
"name" : "Demo organization",
"plan" : "ENTERPRISE",
"createdBy" : "demo@domain.com",
"createdAt" : "2021-12-15T15:15:00.000000999Z",
"masterCurrency" : "EUR",
"masterCountry" : "FR",
"masterLanguage" : "fr",
"masterDistanceUnit" : "KM"
} ]
}
Return a list of organization summaries that the authenticated user can have access to.
Request
GET /api/org/v1/organizations
Response body
The list of available organizations.
field | type | description |
---|---|---|
data | OrganizationSummary[] | |
data[].id | String | Unique identifier of the Organization in Jenji (UUID). |
data[].name | String | Name of the organization, usually the name of the company. |
data[].plan | String | Commercial plan of the organization. One of:
|
data[].createdBy | String | Medium through which the organization was created (backend, mobile application...). |
data[].createdAt | OffsetDateTime | Timestamp of the creation of the organization. |
data[].masterCurrency | String | The reporting currency of the organization. Expenses may be expressed in local currencies, different from the organization currency, but amounts are always converted and reported to the currency of the organization. |
data[].masterCountry | String | The reporting country of the organization. |
data[].masterLanguage | String | The reporting language of the organization. |
data[].masterDistanceUnit | DistanceUnit | Distance unit for the organization. Default is km. |
View an organization
curl -X GET "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687" \
-u API_USER_ID:SECRET_KEY \
{
"id" : "74dbaf20-7f22-45e6-8378-cf33cb775687",
"name" : "Demo organization",
"plan" : "ENTERPRISE",
"createdBy" : "demo@domain.com",
"createdAt" : "2021-02-19T09:51:20.000000987Z",
"masterCurrency" : "EUR",
"masterCountry" : "FR",
"masterLanguage" : "fr",
"availableLanguages" : [ "en", "fr" ],
"categories" : [ {
"id" : "lunch",
"disabled" : false,
"labelsPerLanguage" : {
"en" : "Lunch",
"fr" : "Repas"
},
"order" : 0
} ],
"groups" : [ {
"id" : "root",
"internalId" : "000",
"name" : "Demo organization"
}, {
"id" : "03d48d14-c2fb-4d1e-9c42-2c7594fb3ffe",
"internalId" : "001",
"name" : "Sub group",
"parentGroupId" : "root"
} ],
"userCustomFields" : [ {
"key" : "agency",
"type" : "STRING",
"required" : true,
"labelsPerLanguage" : {
"en" : "Agency",
"fr" : "Agence"
},
"order" : 0
} ]
}
Return the details of an organization.
Request
GET /api/org/v1/organizations/{organizationId}
Response body
The details of the specified organization.
See Organization
Edit an organization
curl -X PATCH "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687" \
-u API_USER_ID:SECRET_KEY \
-H "Content-Type: application/json" \
--data '{
"name" : "New demo name",
"masterLanguage" : "en",
"masterCurrency" : "GBP",
"masterCountry" : "UK"
}'
{
"id" : "74dbaf20-7f22-45e6-8378-cf33cb775687",
"name" : "New demo name",
"plan" : "ENTERPRISE",
"createdBy" : "demo@domain.com",
"createdAt" : "2021-02-19T09:51:20.000000987Z",
"masterCurrency" : "UK",
"masterCountry" : "GBP",
"masterLanguage" : "en",
"availableLanguages" : [ "en", "fr" ],
"categories" : [ {
"id" : "lunch",
"disabled" : false,
"labelsPerLanguage" : {
"en" : "Lunch",
"fr" : "Repas"
},
"order" : 0
} ],
"groups" : [ {
"id" : "root",
"internalId" : "000",
"name" : "Demo organization"
}, {
"id" : "b9846736-eccd-4456-ba75-6e506ca45701",
"internalId" : "001",
"name" : "Sub group",
"parentGroupId" : "root"
} ],
"userCustomFields" : [ {
"key" : "agency",
"type" : "STRING",
"required" : true,
"labelsPerLanguage" : {
"en" : "Agency",
"fr" : "Agence"
},
"order" : 0
} ]
}
Patch the organization value, only non null value will be taken into account.
Request
PATCH /api/org/v1/organizations/{organizationId}
Request body
Patch organization data.
field | type | description |
---|---|---|
name | String | Organization name Empty or null value will be ignored |
masterLanguage | String | Organization default language. Empty string will clear the field, null will be ignored. |
masterCurrency | String | Organization default currency for expenses Empty string will clear the field, null will be ignored. |
masterCountry | String | Organization default country Empty string will clear the field, null will be ignored. |
Response body
An organization is an operating company, for which we want to track expenses. Members of the organization, such as sales representatives, managers, accountants, may gain access to the organization as organization users, to act at the many steps of the workflow of expense management.
See Organization
Create a new group
curl -X POST "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687/groups" \
-u API_USER_ID:SECRET_KEY \
-H "Content-Type: application/json" \
--data '{
"name" : "Sub group 2",
"parentGroupId" : "837e9a99-d05d-4764-8397-4f7e0a92c408",
"internalId" : "007"
}'
{
"id" : "2c73c743-2944-461b-a576-050ff984f962",
"internalId" : "Sub group 2",
"name" : "Sub group 2",
"parentGroupId" : "837e9a99-d05d-4764-8397-4f7e0a92c408",
"createdAt" : "2021-02-19T14:43:59.000000999Z",
"updatedAt" : "2021-02-19T14:43:59.000000999Z"
}
Add a new group to an organization. The caller may specify a parent group to form a hierarchy, or leave the parent null, in which case the group will be created as a direct child of the root group.
Request
POST /api/org/v1/organizations/{organizationId}/groups
Request body
Data used to create the new group.
field | type | description |
---|---|---|
name | String | Mandatory. The name of the organization group, e.g. the designation of the team. |
parentGroupId | String | Optional. The parent group of the group to be created. If left empty, then the group parent is automatically set to the organization root group. |
internalId | String | The code of the group, i.e. team, as known in the organization information system. |
Response body
The newly-created group. To see the entire hierarchy, make a GET on the organization itself.
Update group
# Update name and internal id
curl -X PATCH "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687/groups/2c73c743-2944-461b-a576-050ff984f962" \
-u API_USER_ID:SECRET_KEY \
-H "Content-Type: application/json" \
--data '{
"name" : "Sub group OSS",
"internalId" : "117"
}'
{
"id" : "2c73c743-2944-461b-a576-050ff984f962",
"internalId" : "Sub group OSS",
"name" : "Sub group OSS",
"parentGroupId" : "837e9a99-d05d-4764-8397-4f7e0a92c408",
"createdAt" : "2021-02-19T14:43:59.000000999Z",
"updatedAt" : "2021-02-21T09:26:41.000000999Z"
}
# Update parent group and clear internal id
curl -X PATCH "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687/groups/2c73c743-2944-461b-a576-050ff984f962" \
-u API_USER_ID:SECRET_KEY \
-H "Content-Type: application/json" \
--data '{
"parentGroupId" : "root",
"internalId" : ""
}'
{
"id" : "2c73c743-2944-461b-a576-050ff984f962",
"name" : "Sub group 2",
"parentGroupId" : "root",
"createdAt" : "2021-02-19T14:43:59.000000999Z",
"updatedAt" : "2021-02-21T09:26:41.000000999Z"
}
Update the values of the group's fields.
The values of group already defined but not in the request will not be modified or deleted.
Request
PATCH /api/org/v1/organizations/{organizationId}/groups/{groupId}
Path variables
parameter | type | required | description |
---|---|---|---|
groupId | String | true |
Request body
Custom fields values to update.
field | type | description |
---|---|---|
name | String | The name of the group, e.g. the designation of the team. Can not be an empty string. If null, name is not updated |
parentGroupId | String | The parent group of the group to be created. If empty string, then the group parent is automatically set to the organization root group. If null, parent is not updated |
internalId | String | The code of the group, i.e. team, as known in the organization information system. Pass an empty string to clear the value. If null, internal id is not updated |
Response body
The updated group. To see the entire hierarchy, make a GET on the organization itself.
Update group custom field values
Update the values of the group's custom fields.
The values of group custom fields already defined but not in the request will not be modified or deleted.
A group custom field value in the request that does not already exist will be created.
All group custom fields in the request must have a definition already set.
Request
PATCH /api/org/v1/organizations/{organizationId}/groups/{groupId}/custom-fields
Path variables
parameter | type | required | description |
---|---|---|---|
groupId | String | true |
Request body
Custom fields values to update.
field | type | description |
---|---|---|
customFieldsValues | Map<String,Object> | Mandatory. The map of custom fields values to update. |
Response body
The updated group. To see the entire hierarchy, make a GET on the organization itself.
field | type | description |
---|---|---|
customFieldsValues | Map<String,?> | All group custom field values after update |
List all communications
List all the communications of the organization.
Request
GET /api/org/v1/organizations/{organizationId}/communications
Response body
field | type | description |
---|---|---|
data | OrganizationCommunication[] | |
data[].id | String | Unique identifier of the communication in Jenji (UUID). |
data[].code | String | Code freely defined by a manager to identify a specific communication in a human readable way. |
data[].groupId | String | Identifier of the organization group for which the communication has been defined. |
data[].messagesPerLanguage | Map<String,String> | The messages of the communication, per language, as displayed to front clients (web application, mobile applications). |
data[].level | String | Level of the communication : INFO, WARNING, ERROR, SUCCESS. |
data[].startDate | OffsetDateTime | Start date of the communication. If null, the communication is considered as started. |
data[].endDate | OffsetDateTime | End date of the communication. If null, the communication is considered still running. |
data[].updatedAt | OffsetDateTime | Timestamp of the last modification of the communication. |
Create new communication
Create a new communication for an organization group.
Request
POST /api/org/v1/organizations/{organizationId}/communications
Request body
Create a new organization communication.
field | type | description |
---|---|---|
code | String | Mandatory. Code freely defined by a manager to identify a specific communication in a human readable way. |
groupId | String | Mandatory. Identifier of the organization group for which the communication has been defined. |
messagesPerLanguage | Map<String,String> | Mandatory. The messages of the communication, per language, as displayed to front clients (web application, mobile applications). |
level | String | Mandatory. Level of the communication : INFO, WARNING, ERROR, SUCCESS. |
startDate | OffsetDateTime | Optional. Start date of the communication. If null, the communication is considered as started. |
endDate | OffsetDateTime | Optional. End date of the communication. If null, the communication is considered still running. |
Response body
Any business message defined by an organization group manager to inform all users of that group. ex: 'Please enter all your expenses before the 25th of the month to be reimbursed'.
Update existing communication
Update an existing communication for an organization group.
Request
PUT /api/org/v1/organizations/{organizationId}/communications/{communicationId}
Path variables
parameter | type | required | description |
---|---|---|---|
communicationId | String | true |
Request body
Update an existing communication.
field | type | description |
---|---|---|
code | String | Mandatory. Code freely defined by a manager to identify a specific communication in a human readable way. |
groupId | String | Mandatory. Identifier of the organization group for which the communication has been defined. |
messagesPerLanguage | Map<String,String> | Mandatory. The messages of the communication, per language, as displayed to front clients (web application, mobile applications). |
level | String | Mandatory. Level of the communication : INFO, WARNING, ERROR, SUCCESS. |
startDate | OffsetDateTime | Optional. Start date of the communication. If null, the communication is considered as started. |
endDate | OffsetDateTime | Optional. End date of the communication. If null, the communication is considered still running. |
Response body
Any business message defined by an organization group manager to inform all users of that group. ex: 'Please enter all your expenses before the 25th of the month to be reimbursed'.
Delete a communication
Delete an existing communication.
Request
DELETE /api/org/v1/organizations/{organizationId}/communications/{communicationId}
Path variables
parameter | type | required | description |
---|---|---|---|
communicationId | String | true |
List user activities
List activity for all users of an organization, on the given time period.
Request
GET /api/org/v1/organizations/{organizationId}/user-activities
Query parameters
parameter | type | required | description |
---|---|---|---|
from | LocalDate | true | Start date (format: YYYY-MM-DD). |
to | LocalDate | true | End date, not inclusive (format: YYYY-MM-DD). |
Response body
List of users activities for an organization matching the search criteria.
field | type | description |
---|---|---|
data | DailyUserActivity[] | |
data[].userId | String | The user identifier. Format: UUID v4. |
data[].day | String | The day of activity. Format: YYYY-MM-DD. |
data[].organizationId | String | The organization identifier. Format: UUID v4. |
data[].created | int | The number of expenses created that day. Increased as soon as the user creates a standard, mileage or allowance expense. |
data[].checked | int | In organizations with the compliance step enabled, incremented as soon as the user marks an expense as 'compliant' or 'not compliant'. For organizations with a custom expense workflow, incremented when the user performs an intermediary validation step. Only possible for users with expense verification rights or equivalent profiles. |
data[].decided | int | Incremented as soon as the user marks an expense as accepted or rejected. For organizations with a custom expense workflow, incremented when the user performs the final validation step on an expense. Only possible for users with expense validation rights or equivalent profiles. |
data[].accounted | int | Incremented when an accounting export is marked as 'accounted'. Every expense in the export increments this counter by 1. Only possible for users with accounting rights. |
data[].paid | int | Incremented when a payroll export is marked as 'reimbursed'. Every expense in the export increments this counter by 1. Only possible for users with accounting rights. |
data[].deleted | int | Incremented as soon as the user changes the state of an expense to 'DELETED'. Since Jenji only performs logical deletions, multiple delete/undelete operations on a same expense will increment this counter multiple times. |
data[].ignored | int | The number expense actions that would usually be billed but are ignored because of special organization rules. This field can safely be ignored if no such rules have been contractually defined. |
Org. base customization
Set of methods to create, update or view organization categories.
List categories
curl -X GET "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687/categories" \
-u API_USER_ID:SECRET_KEY \
{
"data" : [ {
"id" : "lunch",
"disabled" : false,
"labelsPerLanguage" : {
"en" : "Lunch",
"fr" : "Repas"
},
"order" : 0
}, {
"id" : "taxi",
"disabled" : true,
"labelsPerLanguage" : {
"en" : "Taxi",
"fr" : "Taxi"
},
"order" : 99
} ]
}
curl -X GET "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687/categories?disabled=false" \
-u API_USER_ID:SECRET_KEY \
{
"data" : [ {
"id" : "lunch",
"disabled" : false,
"labelsPerLanguage" : {
"en" : "Lunch",
"fr" : "Repas"
},
"order" : 0
} ]
}
Fetch the list of expense categories
Request
GET /api/org/v1/organizations/{organizationId}/categories
Query parameters
parameter | type | required | description |
---|---|---|---|
disabled | Boolean | false | filter categories on disabled attribute: using false will return only active categories |
Response body
field | type | description |
---|---|---|
data | Category[] | |
data[].id | String | Identifier of the category. This is usually a code unique within the organization, either a standard code for a Jenji category, or a custom code for a custom category. |
data[].disabled | Boolean | The category may be disabled, i.e. is not usable on new expenses. Previous expenses which reference this category may still use it. |
data[].notSelectable | Boolean | The category is still valid, but not usable. |
data[].labelsPerLanguage | Map<String,String> | The labels of the category, per language, as displayed to front clients (web application, mobile applications). Organization which define custom categories are encouraged to define labels for all the languages they manage. |
data[].ocrMappedStandardCategories | String[] | List of standard category codes to map onto the custom category, when our AI-based agent analyzes a receipt and derives a standard category which has been replaced by a custom category by the organization. |
data[].order | Integer | Order of the category for front clients. |
data[].parentCategoryId | String | Categories may be hierarchical; child categories reference a parent category. |
data[].iconId | String | The identifier of the icon used to display the category in front clients. |
data[].colorId | String | The identifier of the color used to display the category in front clients. |
data[].scopeCondition | ScopeCondition | Allow to manage the visibility of the category, using advanced conditions |
Update all categories
curl -X PUT "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687/categories" \
-u API_USER_ID:SECRET_KEY \
-H "Content-Type: application/json" \
--data '[ {
"id" : "gift",
"disabled" : false,
"labelsPerLanguage" : {
"en" : "Daily lunch",
"fr" : "Daily lunch"
},
"order" : 0
} ]'
{
"data" : [ { }, {
"id" : "lunch",
"disabled" : true,
"order" : 99
}, {
"id" : "taxi",
"disabled" : true,
"labelsPerLanguage" : {
"en" : "Taxi",
"fr" : "Taxi"
},
"order" : 99
} ]
}
Update the full list of categories.
Categories not included in the body (using the id
attribute)
will be disabled with an order putting them at the end of list.
Disabled categories will be returned in the answer.
Request
PUT /api/org/v1/organizations/{organizationId}/categories
Request body
new list of categories to apply
field | type | description |
---|---|---|
id | String | Identifier of the category. This is usually a code unique within the organization, either a standard code for a Jenji category, or a custom code for a custom category. |
disabled | Boolean | The category may be disabled, i.e. is not usable on new expenses. Previous expenses which reference this category may still use it. |
notSelectable | Boolean | The category is still valid, but not usable. |
labelsPerLanguage | Map<String,String> | The labels of the category, per language, as displayed to front clients (web application, mobile applications). Organization which define custom categories are encouraged to define labels for all the languages they manage. |
ocrMappedStandardCategories | String[] | List of standard category codes to map onto the custom category, when our AI-based agent analyzes a receipt and derives a standard category which has been replaced by a custom category by the organization. |
order | Integer | Order of the category for front clients. |
parentCategoryId | String | Categories may be hierarchical; child categories reference a parent category. Only one category level is authorized |
iconId | String | The identifier of the icon used to display the category in front clients. |
colorId | String | The identifier of the color used to display the category in front clients. |
scopeCondition | ScopeCondition | Allow to manage the availability of the category, using advanced conditions |
Response body
The organization categories after update.
field | type | description |
---|---|---|
data | Category[] | |
data[].id | String | Identifier of the category. This is usually a code unique within the organization, either a standard code for a Jenji category, or a custom code for a custom category. |
data[].disabled | Boolean | The category may be disabled, i.e. is not usable on new expenses. Previous expenses which reference this category may still use it. |
data[].notSelectable | Boolean | The category is still valid, but not usable. |
data[].labelsPerLanguage | Map<String,String> | The labels of the category, per language, as displayed to front clients (web application, mobile applications). Organization which define custom categories are encouraged to define labels for all the languages they manage. |
data[].ocrMappedStandardCategories | String[] | List of standard category codes to map onto the custom category, when our AI-based agent analyzes a receipt and derives a standard category which has been replaced by a custom category by the organization. |
data[].order | Integer | Order of the category for front clients. |
data[].parentCategoryId | String | Categories may be hierarchical; child categories reference a parent category. |
data[].iconId | String | The identifier of the icon used to display the category in front clients. |
data[].colorId | String | The identifier of the color used to display the category in front clients. |
data[].scopeCondition | ScopeCondition | Allow to manage the visibility of the category, using advanced conditions |
Update one category
Update a single category.
Disabling a category will disable all sub categories
Request
PUT /api/org/v1/organizations/{organizationId}/categories/{categoryId}
Path variables
parameter | type | required | description |
---|---|---|---|
categoryId | String | true | id of category to update |
Request body
new category values
field | type | description |
---|---|---|
disabled | Boolean | The category may be disabled, i.e. is not usable on new expenses. Previous expenses which reference this category may still use it. |
notSelectable | Boolean | The category is still valid, but not usable. |
labelsPerLanguage | Map<String,String> | The labels of the category, per language, as displayed to front clients (web application, mobile applications). Organization which define custom categories are encouraged to define labels for all the languages they manage. |
ocrMappedStandardCategories | String[] | List of standard category codes to map onto the custom category, when our AI-based agent analyzes a receipt and derives a standard category which has been replaced by a custom category by the organization. |
order | Integer | Order of the category for front clients. |
parentCategoryId | String | Categories may be hierarchical; child categories reference a parent category. Only one category level is authorized |
iconId | String | The identifier of the icon used to display the category in front clients. |
colorId | String | The identifier of the color used to display the category in front clients. |
scopeCondition | ScopeCondition | Allow to manage the availability of the category, using advanced conditions |
Response body
The updated category.
See Category
List payment methods
Fetch the list of expense payment methods
Request
GET /api/org/v1/organizations/{organizationId}/payment-methods
Query parameters
parameter | type | required | description |
---|---|---|---|
disabled | Boolean | false | filter payment methods on disabled attribute: using false will return only active payment methods |
Response body
field | type | description |
---|---|---|
data | PaymentMethod[] | |
data[].id | String | Unique identifier of the payment method in Jenji (UUID). |
data[].label | String | The label of the payment method, to help the user select the appropriate method when creating the expense. |
data[].labelsPerLanguage | Map<String,String> | The labels of the payment method, per language, as displayed to front clients (web application, mobile applications). |
data[].code | String | The code of the payment method, available in various exports. |
data[].reimbursable | Boolean | Whether any expense made with this payment is reimbursable. A company credit card, for instance, would not incur reimbursable expenses, while a personal credit card would require reimbursements. |
data[].dissociated | Boolean | Whether the payment method is dissociated. |
data[].disabled | Boolean | Whether the payment method is now disabled, i.e. may not be used on new expenses. |
data[].transactionProvider | String | A payment method may be associated with a transaction provider, such as a bank. Jenji offers many integration features with existing banks, whereby an organization may allow Jenji to retrieve bank transactions from its bank, so as to automatically reconcile an expense with a matching bank transaction. |
Update all payment methods
Update the full list of payment methods. Update existing payment method matching the id
attribute, create the
new ones.
Payment methods not included in the body (using the id
attribute)
will be disabled with an order putting them at the end of list.
Disabled payment methods will be returned in the answer.
Request
PUT /api/org/v1/organizations/{organizationId}/payment-methods
Request body
new list of payment methods to apply
field | type | description |
---|---|---|
id | String | Unique identifier of the payment method in Jenji (UUID). If null, a random UUID will be generated. |
labelsPerLanguage | Map<String,String> | The labels of the payment method, per language, as displayed to front clients (web application, mobile applications). |
code | String | The code of the payment method, available in various exports. |
reimbursable | Boolean | Whether any expense made with this payment is reimbursable. A company credit card, for instance, would not incur reimbursable expenses, while a personal credit card would require reimbursements. |
disabled | Boolean | Whether the payment method is now disabled, i.e. may not be used on new expenses. |
Response body
The organization payment methods after update.
field | type | description |
---|---|---|
data | PaymentMethod[] | |
data[].id | String | Unique identifier of the payment method in Jenji (UUID). |
data[].label | String | The label of the payment method, to help the user select the appropriate method when creating the expense. |
data[].labelsPerLanguage | Map<String,String> | The labels of the payment method, per language, as displayed to front clients (web application, mobile applications). |
data[].code | String | The code of the payment method, available in various exports. |
data[].reimbursable | Boolean | Whether any expense made with this payment is reimbursable. A company credit card, for instance, would not incur reimbursable expenses, while a personal credit card would require reimbursements. |
data[].dissociated | Boolean | Whether the payment method is dissociated. |
data[].disabled | Boolean | Whether the payment method is now disabled, i.e. may not be used on new expenses. |
data[].transactionProvider | String | A payment method may be associated with a transaction provider, such as a bank. Jenji offers many integration features with existing banks, whereby an organization may allow Jenji to retrieve bank transactions from its bank, so as to automatically reconcile an expense with a matching bank transaction. |
Create a payment method
Create a single payment method.
Request
POST /api/org/v1/organizations/{organizationId}/payment-methods
Request body
new payment method
field | type | description |
---|---|---|
labelsPerLanguage | Map<String,String> | The labels of the payment method, per language, as displayed to front clients (web application, mobile applications). |
code | String | The code of the payment method, available in various exports. |
reimbursable | Boolean | Whether any expense made with this payment is reimbursable. A company credit card, for instance, would not incur reimbursable expenses, while a personal credit card would require reimbursements. |
disabled | Boolean | Whether the payment method is now disabled, i.e. may not be used on new expenses. |
Response body
The created payment method.
See PaymentMethod
Update a payment method
Update a single payment method.
Request
PUT /api/org/v1/organizations/{organizationId}/payment-methods/{paymentMethodId}
Path variables
parameter | type | required | description |
---|---|---|---|
paymentMethodId | String | true | id of payment method to update |
Request body
new payment method values
field | type | description |
---|---|---|
id | String | Unique identifier of the payment method in Jenji (UUID). If null, a random UUID will be generated. |
labelsPerLanguage | Map<String,String> | The labels of the payment method, per language, as displayed to front clients (web application, mobile applications). |
code | String | The code of the payment method, available in various exports. |
reimbursable | Boolean | Whether any expense made with this payment is reimbursable. A company credit card, for instance, would not incur reimbursable expenses, while a personal credit card would require reimbursements. |
disabled | Boolean | Whether the payment method is now disabled, i.e. may not be used on new expenses. |
Response body
The updated payment method.
See PaymentMethod
List allowances templates
curl -X GET "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687/allowance-templates" \
-u API_USER_ID:SECRET_KEY \
{
"data" : [ {
"templateId" : "1b2c3101-cda8-49ad-afe1-4ef494bbbf38",
"labelsPerLanguage" : {
"en" : "Lunch",
"fr" : "Repas"
},
"total" : 22,
"currency" : "EUR",
"country" : "FR",
"category" : "lunch",
"paymentMethodId" : "8288ac38-8d04-484c-89ab-6bee22e8b602",
"order" : 0,
"disabled" : false
}, {
"templateId" : "6629e7bb-94ba-4ccf-8a06-0c3efe55a075",
"labelsPerLanguage" : {
"en" : "Single night",
"fr" : "Nuit hotel"
},
"total" : 75,
"currency" : "EUR",
"country" : "FR",
"category" : "hotel",
"paymentMethodId" : "8288ac38-8d04-484c-89ab-6bee22e8b602",
"order" : 1,
"disabled" : true
} ]
}
curl -X GET "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687/allowance-templates?disabled=false" \
-u API_USER_ID:SECRET_KEY \
{
"data" : [ {
"templateId" : "cbe1f3ba-00bd-41f9-b86a-732b0d1a0c13",
"labelsPerLanguage" : {
"en" : "Lunch",
"fr" : "Repas"
},
"total" : 22,
"currency" : "EUR",
"country" : "FR",
"category" : "lunch",
"paymentMethodId" : "8288ac38-8d04-484c-89ab-6bee22e8b602",
"order" : 0,
"disabled" : false
} ]
}
Fetch the list of allowances templates
Request
GET /api/org/v1/organizations/{organizationId}/allowance-templates
Query parameters
parameter | type | required | description |
---|---|---|---|
disabled | Boolean | false | filter templates on disabled attribute: using false will return only active templates |
Response body
field | type | description |
---|---|---|
data | AllowanceTemplate[] | |
data[].templateId | String | Template id, value must be passed when creating an allowance expense. |
data[].labelsPerLanguage | Map<String,String> | The labels of the allowance template, per language, as displayed to front clients (web application, mobile applications). |
data[].total | BigDecimal | The total amount of the allowance. |
data[].currency | String | The currency of the total amount. (EUR, USD, ...) |
data[].country | String | The country of the expense. (FR, US, ...) |
data[].category | String | The category of the expense. |
data[].paymentMethodId | String | The identifier of the payment method which was used to pay the expense (for instance a credit card). Payment methods are declared on the groups of the organization. |
data[].order | int | Template order in the front selection list. |
data[].disabled | Boolean | Disable the template, making creation of new expense from it impossible. |
data[].requireReceipt | Boolean | User must add a receipt with the allowance (default false). If no receipt is required, the category icon will be used instead. |
data[].emptyDate | Boolean | Empty expense date on page load (if false, the current date is pre-filled) |
data[].creationCondition | ScopeCondition | Allow to manage the availability of the template for the users, using advanced conditions |
Create allowances templates
curl -X POST "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687/allowance-templates" \
-u API_USER_ID:SECRET_KEY \
-H "Content-Type: application/json" \
--data '{
"labelsPerLanguage" : {
"en" : "Internet",
"fr" : "Internet"
},
"total" : 30,
"currency" : "EUR",
"country" : "FR",
"category" : "other",
"paymentMethodId" : "8288ac38-8d04-484c-89ab-6bee22e8b602",
"disabled" : false
}'
{
"templateId" : "028dfe34-445d-4200-b727-bacba71f3ce6",
"labelsPerLanguage" : {
"en" : "Internet",
"fr" : "Internet"
},
"total" : 30,
"currency" : "EUR",
"country" : "FR",
"category" : "other",
"paymentMethodId" : "8288ac38-8d04-484c-89ab-6bee22e8b602",
"order" : 3,
"disabled" : false,
"requireReceipt" : false
}
Create a new allowance template
Request
POST /api/org/v1/organizations/{organizationId}/allowance-templates
Request body
Allowance template will be provided as a way to create an allowance, which is an expense with values filled from template at creation and not updatable after (like name, total, category, ...).
User will be able to update expense time, explanation, custom fields, ...
Values are copied on expense creation, updating a template after will not affect existing expenses.
field | type | description |
---|---|---|
labelsPerLanguage | Map<String,String> | The labels of the allowance template, per language, as displayed to front clients (web application, mobile applications). Created expense will use the label in the user language as label vaule. |
total | BigDecimal | The total amount of the allowance. |
currency | String | The currency of the total amount. |
country | String | The country of the expense. |
category | String | The category of the expense. |
paymentMethodId | String | The identifier of the payment method which was used to pay the expense (for instance a credit card). Payment methods are declared on the groups of the organization. |
order | Integer | Template order in the front selection list. Using a null value will put the template at the end of the list. |
disabled | Boolean | Disable the template, making creation of new expense from it impossible. Null value will be considered as false. |
requireReceipt | Boolean | User must add a receipt with the allowance (default false). If no receipt is required, the category icon will be used instead. Null value will be considered as false. |
creationCondition | ScopeCondition | Allow to manage the availability of the template for the users, using advanced conditions |
Response body
Allowance template will be provided as a way to create an allowance, which is an expense with values filled from template at creation and not updatable after (like name, total, category, ...).
User will be able to update expense time, explanation, custom fields, ...
Values are copied on expense creation, updating a template after will not affect existing expenses.
Update allowances templates
curl -X PUT "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687/allowance-templates/{templateId}" \
-u API_USER_ID:SECRET_KEY \
-H "Content-Type: application/json" \
--data '{
"labelsPerLanguage" : {
"en" : "Internet",
"fr" : "Internet"
},
"total" : 28,
"currency" : "EUR",
"country" : "FR",
"category" : "other",
"paymentMethodId" : "8288ac38-8d04-484c-89ab-6bee22e8b602",
"disabled" : false
}'
{
"templateId" : "028dfe34-445d-4200-b727-bacba71f3ce6",
"labelsPerLanguage" : {
"en" : "Internet",
"fr" : "Internet"
},
"total" : 28,
"currency" : "EUR",
"country" : "FR",
"category" : "other",
"paymentMethodId" : "8288ac38-8d04-484c-89ab-6bee22e8b602",
"order" : 3,
"disabled" : false,
"requireReceipt" : false
}
Update an existing allowance template. If no order is passed, it will keep the current order
Request
PUT /api/org/v1/organizations/{organizationId}/allowance-templates/{templateId}
Path variables
parameter | type | required | description |
---|---|---|---|
templateId | String | true |
Request body
Allowance template will be provided as a way to create an allowance, which is an expense with values filled from template at creation and not updatable after (like name, total, category, ...).
User will be able to update expense time, explanation, custom fields, ...
Values are copied on expense creation, updating a template after will not affect existing expenses.
field | type | description |
---|---|---|
labelsPerLanguage | Map<String,String> | The labels of the allowance template, per language, as displayed to front clients (web application, mobile applications). Created expense will use the label in the user language as label vaule. |
total | BigDecimal | The total amount of the allowance. |
currency | String | The currency of the total amount. |
country | String | The country of the expense. |
category | String | The category of the expense. |
paymentMethodId | String | The identifier of the payment method which was used to pay the expense (for instance a credit card). Payment methods are declared on the groups of the organization. |
order | Integer | Template order in the front selection list. Using a null value will put the template at the end of the list. |
disabled | Boolean | Disable the template, making creation of new expense from it impossible. Null value will be considered as false. |
requireReceipt | Boolean | User must add a receipt with the allowance (default false). If no receipt is required, the category icon will be used instead. Null value will be considered as false. |
creationCondition | ScopeCondition | Allow to manage the availability of the template for the users, using advanced conditions |
Response body
Allowance template will be provided as a way to create an allowance, which is an expense with values filled from template at creation and not updatable after (like name, total, category, ...).
User will be able to update expense time, explanation, custom fields, ...
Values are copied on expense creation, updating a template after will not affect existing expenses.
Org. custom-fields
Custom fields are analytic fields freely defined by an organization, which may be filled in by a user when creating an expense.
List expense custom fields
curl -X GET "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687/custom-fields/expense" \
-u API_USER_ID:SECRET_KEY \
{
"data" : [ {
"key" : "meal-type",
"type" : "LIST",
"listId" : "meal-type",
"required" : true,
"labelsPerLanguage" : {
"en" : "Meal type",
"fr" : "Type repas"
},
"order" : 0
} ]
}
Fetch the list of expense custom fields
Request
GET /api/org/v1/organizations/{organizationId}/custom-fields/expense
Response body
field | type | description |
---|---|---|
data | CustomField[] | |
data[].key | String | This is the unique code of the custom field. |
data[].type | String | The custom field may only contain values of the same type. Currently supported types include:
New types may be regularly added. |
data[].minimumValue | BigDecimal | Only for custom fields of type NUMBER or LONG. The minimum value allowed for this custom field. |
data[].maximumValue | BigDecimal | Only for custom fields of type NUMBER or LONG. The maximum value allowed for this custom field. |
data[].listId | String | Only for custom fields of type LIST, generated by the backend. ID required to manipulate the list of options associated with this custom field. |
data[].required | Boolean | Whether the custom field is mandatory when creating an expense. |
data[].labelsPerLanguage | Map<String,String> | Localized labels of the custom fields. Organizations are encouraged to provide labels for each language that they manage. |
data[].editableByGroups | String[] | List of identifiers of organization groups which may use and edit the values of a custom field. |
data[].visibleByGroups | String[] | List of identifiers of organization groups which may use and view (but not edit) the values of a custom field. Groups that may edit a custom field, may also view it. |
data[].order | Integer | Order of the custom field, for front clients. |
data[].visibleScopeCondition | ScopeCondition | Allow to manage the visibility using advanced conditions |
data[].configuredByAPI | Boolean | Whether this custom field may be configured, updated or deleted only by external API calls, and not manually within the app by an organization user. Setting this flag to true is an equivalent of setting the 3 flags {disableConfiguration, disableOptionConfiguration, disableDeletion} to true. This flag takes precedence over the other flags. |
data[].disableConfiguration | Boolean | Disable the button to configure the custom field within the app |
data[].disableOptionConfiguration | Boolean | Disable the button to configure custom field options (for collection types) within the app |
data[].disableDeletion | Boolean | Disable the button to delete the custom field within the app |
data[].validation | CustomFieldValidation | validation defines rules for custom field values. |
Update all expense custom fields
curl -X PUT "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687/custom-fields/expense" \
-u API_USER_ID:SECRET_KEY \
-H "Content-Type: application/json" \
--data '[ {
"type" : "LIST",
"required" : false,
"labelsPerLanguage" : {
"en" : "Meal type",
"fr" : "Type repas"
},
"order" : 0,
"key" : "meal-type"
}, {
"type" : "LONG",
"required" : true,
"labelsPerLanguage" : {
"en" : "Number of nights",
"fr" : "Nombre de nuits"
},
"order" : 1,
"key" : "night-number"
} ]'
{
"data" : [ {
"key" : "meal-type",
"type" : "LIST",
"listId" : "meal-type",
"required" : false,
"labelsPerLanguage" : {
"en" : "Meal type",
"fr" : "Type repas"
},
"order" : 0
}, {
"key" : "night-number",
"type" : "LONG",
"required" : true,
"labelsPerLanguage" : {
"en" : "Number of nights",
"fr" : "Nombre de nuits"
},
"order" : 1
} ]
}
Update the full list of expense custom fields.
Expense custom fields not included in the body (using the key
attribute)
will be disabled with an order putting them at the end of list.
Disabled expense custom fields will be returned in the answer.
Request
PUT /api/org/v1/organizations/{organizationId}/custom-fields/expense
Request body
new list of expense custom fields to apply
field | type | description |
---|---|---|
type | String | The custom field may only contain values of the same type. Currently supported types include:
New types may be regularly added. |
required | Boolean | Whether the custom field is mandatory when creating an expense. |
labelsPerLanguage | Map<String,String> | Localized labels of the custom fields. Organizations are encouraged to provide labels for each language that they manage. |
editableByGroups | String[] | List of identifiers of organization groups which may use and edit the values of a custom field. |
visibleByGroups | String[] | List of identifiers of organization groups which may use and view (but not edit) the values of a custom field. Groups that may edit a custom field, may also view it. |
order | Integer | Order of the custom field, for front clients. |
visibleScopeCondition | ScopeCondition | Allow to manage the visibility using advanced conditions |
configuredByAPI | Boolean | Whether this custom field may be configured, updated or deleted only by external API calls, and not manually within the app by an organization user. Setting this flag to true is an equivalent of setting the 3 flags {disableConfiguration, disableOptionConfiguration, disableDeletion} to true. This flag takes precedence over the other flags. |
disableConfiguration | Boolean | Disable the button to configure the custom field within the app |
disableOptionConfiguration | Boolean | Disable the button to configure custom field options (for collection types) within the app |
disableDeletion | Boolean | Disable the button to delete the custom field within the app |
validation | CustomFieldValidation | |
validation.minimumValue | BigDecimal | Only for custom fields of type NUMBER or LONG. The minimum value allowed for this custom field. |
validation.maximumValue | BigDecimal | Only for custom fields of type NUMBER or LONG. The maximum value allowed for this custom field. |
key | String | This is the unique code of the custom field. |
editableScopeCondition | ScopeCondition | Allow to manage the edibility using advanced conditions |
Response body
The organization expense custom fields after update.
field | type | description |
---|---|---|
data | CustomField[] | |
data[].key | String | This is the unique code of the custom field. |
data[].type | String | The custom field may only contain values of the same type. Currently supported types include:
New types may be regularly added. |
data[].minimumValue | BigDecimal | Only for custom fields of type NUMBER or LONG. The minimum value allowed for this custom field. |
data[].maximumValue | BigDecimal | Only for custom fields of type NUMBER or LONG. The maximum value allowed for this custom field. |
data[].listId | String | Only for custom fields of type LIST, generated by the backend. ID required to manipulate the list of options associated with this custom field. |
data[].required | Boolean | Whether the custom field is mandatory when creating an expense. |
data[].labelsPerLanguage | Map<String,String> | Localized labels of the custom fields. Organizations are encouraged to provide labels for each language that they manage. |
data[].editableByGroups | String[] | List of identifiers of organization groups which may use and edit the values of a custom field. |
data[].visibleByGroups | String[] | List of identifiers of organization groups which may use and view (but not edit) the values of a custom field. Groups that may edit a custom field, may also view it. |
data[].order | Integer | Order of the custom field, for front clients. |
data[].visibleScopeCondition | ScopeCondition | Allow to manage the visibility using advanced conditions |
data[].configuredByAPI | Boolean | Whether this custom field may be configured, updated or deleted only by external API calls, and not manually within the app by an organization user. Setting this flag to true is an equivalent of setting the 3 flags {disableConfiguration, disableOptionConfiguration, disableDeletion} to true. This flag takes precedence over the other flags. |
data[].disableConfiguration | Boolean | Disable the button to configure the custom field within the app |
data[].disableOptionConfiguration | Boolean | Disable the button to configure custom field options (for collection types) within the app |
data[].disableDeletion | Boolean | Disable the button to delete the custom field within the app |
data[].validation | CustomFieldValidation | validation defines rules for custom field values. |
Update one expense custom field
curl -X PUT "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687/custom-fields/expense/{customFieldKey}" \
-u API_USER_ID:SECRET_KEY \
-H "Content-Type: application/json" \
--data '[ {
"type" : "LIST",
"required" : false,
"labelsPerLanguage" : {
"en" : "Meal type",
"fr" : "Type repas"
},
"order" : 0,
"key" : "meal-type"
}, {
"type" : "LONG",
"required" : true,
"labelsPerLanguage" : {
"en" : "Number of nights",
"fr" : "Nombre de nuits"
},
"order" : 1,
"key" : "night-number"
} ]'
{
"data" : [ {
"key" : "meal-type",
"type" : "LIST",
"listId" : "meal-type",
"required" : false,
"labelsPerLanguage" : {
"en" : "Meal type",
"fr" : "Type repas"
},
"order" : 0
}, {
"key" : "night-number",
"type" : "LONG",
"required" : true,
"labelsPerLanguage" : {
"en" : "Number of nights",
"fr" : "Nombre de nuits"
},
"order" : 1
} ]
}
curl -X PUT "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687/custom-fields/expense/night-number" \
-u API_USER_ID:SECRET_KEY \
-H "Content-Type: application/json" \
--data '{
"required" : true,
"labelsPerLanguage" : {
"en" : "Number of nights",
"fr" : "Nombre de nuits"
},
"order" : 1,
"visibleScopeCondition" : {
"type" : "EBF_EQ",
"field" : "CATEGORY",
"value" : "hotel"
}
}'
{
"key" : "night-number",
"type" : "LONG",
"required" : true,
"labelsPerLanguage" : {
"en" : "Number of nights",
"fr" : "Nombre de nuits"
},
"order" : 1,
"visibleScopeCondition" : {
"type" : "EBF_EQ",
"field" : "CATEGORY",
"value" : "hotel"
}
}
Update a single expense custom field.
Request
PUT /api/org/v1/organizations/{organizationId}/custom-fields/expense/{customFieldKey}
Path variables
parameter | type | required | description |
---|---|---|---|
customFieldKey | String | true | id of expense custom field to update |
Request body
new expense custom field values
field | type | description |
---|---|---|
type | String | The custom field may only contain values of the same type. Currently supported types include:
New types may be regularly added. |
required | Boolean | Whether the custom field is mandatory when creating an expense. |
labelsPerLanguage | Map<String,String> | Localized labels of the custom fields. Organizations are encouraged to provide labels for each language that they manage. |
editableByGroups | String[] | List of identifiers of organization groups which may use and edit the values of a custom field. |
visibleByGroups | String[] | List of identifiers of organization groups which may use and view (but not edit) the values of a custom field. Groups that may edit a custom field, may also view it. |
order | Integer | Order of the custom field, for front clients. |
visibleScopeCondition | ScopeCondition | Allow to manage the visibility using advanced conditions |
configuredByAPI | Boolean | Whether this custom field may be configured, updated or deleted only by external API calls, and not manually within the app by an organization user. Setting this flag to true is an equivalent of setting the 3 flags {disableConfiguration, disableOptionConfiguration, disableDeletion} to true. This flag takes precedence over the other flags. |
disableConfiguration | Boolean | Disable the button to configure the custom field within the app |
disableOptionConfiguration | Boolean | Disable the button to configure custom field options (for collection types) within the app |
disableDeletion | Boolean | Disable the button to delete the custom field within the app |
validation | CustomFieldValidation | |
validation.minimumValue | BigDecimal | Only for custom fields of type NUMBER or LONG. The minimum value allowed for this custom field. |
validation.maximumValue | BigDecimal | Only for custom fields of type NUMBER or LONG. The maximum value allowed for this custom field. |
Response body
The updated expense custom fields
See CustomField
Delete one expense custom field
curl -X DELETE "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687/custom-fields/expense/night-number" \
-u API_USER_ID:SECRET_KEY \
null
Delete a single expense custom field.
Request
DELETE /api/org/v1/organizations/{organizationId}/custom-fields/expense/{customFieldKey}
Path variables
parameter | type | required | description |
---|---|---|---|
customFieldKey | String | true | id of the expense custom field to delete |
Response body
204 No Content
field | type | description |
---|
Delete one vehicle custom field
Delete a single vehicle custom field.
Request
DELETE /api/org/v1/organizations/{organizationId}/custom-fields/vehicle/{customFieldKey}
Path variables
parameter | type | required | description |
---|---|---|---|
customFieldKey | String | true | id of the vehicle custom field to delete |
Response body
204 No Content
field | type | description |
---|
List vehicle custom fields
Fetch the list of vehicle custom fields
Request
GET /api/org/v1/organizations/{organizationId}/custom-fields/vehicle
Response body
field | type | description |
---|---|---|
data | CustomField[] | |
data[].key | String | This is the unique code of the custom field. |
data[].type | String | The custom field may only contain values of the same type. Currently supported types include:
New types may be regularly added. |
data[].minimumValue | BigDecimal | Only for custom fields of type NUMBER or LONG. The minimum value allowed for this custom field. |
data[].maximumValue | BigDecimal | Only for custom fields of type NUMBER or LONG. The maximum value allowed for this custom field. |
data[].listId | String | Only for custom fields of type LIST, generated by the backend. ID required to manipulate the list of options associated with this custom field. |
data[].required | Boolean | Whether the custom field is mandatory when creating an expense. |
data[].labelsPerLanguage | Map<String,String> | Localized labels of the custom fields. Organizations are encouraged to provide labels for each language that they manage. |
data[].editableByGroups | String[] | List of identifiers of organization groups which may use and edit the values of a custom field. |
data[].visibleByGroups | String[] | List of identifiers of organization groups which may use and view (but not edit) the values of a custom field. Groups that may edit a custom field, may also view it. |
data[].order | Integer | Order of the custom field, for front clients. |
data[].visibleScopeCondition | ScopeCondition | Allow to manage the visibility using advanced conditions |
data[].configuredByAPI | Boolean | Whether this custom field may be configured, updated or deleted only by external API calls, and not manually within the app by an organization user. Setting this flag to true is an equivalent of setting the 3 flags {disableConfiguration, disableOptionConfiguration, disableDeletion} to true. This flag takes precedence over the other flags. |
data[].disableConfiguration | Boolean | Disable the button to configure the custom field within the app |
data[].disableOptionConfiguration | Boolean | Disable the button to configure custom field options (for collection types) within the app |
data[].disableDeletion | Boolean | Disable the button to delete the custom field within the app |
data[].validation | CustomFieldValidation | validation defines rules for custom field values. |
Update all vehicle custom fields
Update the full list of vehicle custom fields.
Vehicle custom fields not included in the body (using the key
attribute)
will be disabled with an order putting them at the end of list.
Disabled vehicle custom fields will be returned in the answer.
Request
PUT /api/org/v1/organizations/{organizationId}/custom-fields/vehicle
Request body
new list of vehicle custom fields to apply
field | type | description |
---|---|---|
type | String | The custom field may only contain values of the same type. Currently supported types include:
New types may be regularly added. |
required | Boolean | Whether the custom field is mandatory when creating an expense. |
labelsPerLanguage | Map<String,String> | Localized labels of the custom fields. Organizations are encouraged to provide labels for each language that they manage. |
editableByGroups | String[] | List of identifiers of organization groups which may use and edit the values of a custom field. |
visibleByGroups | String[] | List of identifiers of organization groups which may use and view (but not edit) the values of a custom field. Groups that may edit a custom field, may also view it. |
order | Integer | Order of the custom field, for front clients. |
visibleScopeCondition | ScopeCondition | Allow to manage the visibility using advanced conditions |
configuredByAPI | Boolean | Whether this custom field may be configured, updated or deleted only by external API calls, and not manually within the app by an organization user. Setting this flag to true is an equivalent of setting the 3 flags {disableConfiguration, disableOptionConfiguration, disableDeletion} to true. This flag takes precedence over the other flags. |
disableConfiguration | Boolean | Disable the button to configure the custom field within the app |
disableOptionConfiguration | Boolean | Disable the button to configure custom field options (for collection types) within the app |
disableDeletion | Boolean | Disable the button to delete the custom field within the app |
validation | CustomFieldValidation | |
validation.minimumValue | BigDecimal | Only for custom fields of type NUMBER or LONG. The minimum value allowed for this custom field. |
validation.maximumValue | BigDecimal | Only for custom fields of type NUMBER or LONG. The maximum value allowed for this custom field. |
key | String | This is the unique code of the custom field. |
editableScopeCondition | ScopeCondition | Allow to manage the edibility using advanced conditions |
Response body
The organization custom fields after update.
field | type | description |
---|---|---|
data | CustomField[] | |
data[].key | String | This is the unique code of the custom field. |
data[].type | String | The custom field may only contain values of the same type. Currently supported types include:
New types may be regularly added. |
data[].minimumValue | BigDecimal | Only for custom fields of type NUMBER or LONG. The minimum value allowed for this custom field. |
data[].maximumValue | BigDecimal | Only for custom fields of type NUMBER or LONG. The maximum value allowed for this custom field. |
data[].listId | String | Only for custom fields of type LIST, generated by the backend. ID required to manipulate the list of options associated with this custom field. |
data[].required | Boolean | Whether the custom field is mandatory when creating an expense. |
data[].labelsPerLanguage | Map<String,String> | Localized labels of the custom fields. Organizations are encouraged to provide labels for each language that they manage. |
data[].editableByGroups | String[] | List of identifiers of organization groups which may use and edit the values of a custom field. |
data[].visibleByGroups | String[] | List of identifiers of organization groups which may use and view (but not edit) the values of a custom field. Groups that may edit a custom field, may also view it. |
data[].order | Integer | Order of the custom field, for front clients. |
data[].visibleScopeCondition | ScopeCondition | Allow to manage the visibility using advanced conditions |
data[].configuredByAPI | Boolean | Whether this custom field may be configured, updated or deleted only by external API calls, and not manually within the app by an organization user. Setting this flag to true is an equivalent of setting the 3 flags {disableConfiguration, disableOptionConfiguration, disableDeletion} to true. This flag takes precedence over the other flags. |
data[].disableConfiguration | Boolean | Disable the button to configure the custom field within the app |
data[].disableOptionConfiguration | Boolean | Disable the button to configure custom field options (for collection types) within the app |
data[].disableDeletion | Boolean | Disable the button to delete the custom field within the app |
data[].validation | CustomFieldValidation | validation defines rules for custom field values. |
Update one vehicle custom field
Update a single vehicle custom field.
Request
PUT /api/org/v1/organizations/{organizationId}/custom-fields/vehicle/{customFieldKey}
Path variables
parameter | type | required | description |
---|---|---|---|
customFieldKey | String | true | id of vehicle custom field to update |
Request body
new vehicle custom field values
field | type | description |
---|---|---|
type | String | The custom field may only contain values of the same type. Currently supported types include:
New types may be regularly added. |
required | Boolean | Whether the custom field is mandatory when creating an expense. |
labelsPerLanguage | Map<String,String> | Localized labels of the custom fields. Organizations are encouraged to provide labels for each language that they manage. |
editableByGroups | String[] | List of identifiers of organization groups which may use and edit the values of a custom field. |
visibleByGroups | String[] | List of identifiers of organization groups which may use and view (but not edit) the values of a custom field. Groups that may edit a custom field, may also view it. |
order | Integer | Order of the custom field, for front clients. |
visibleScopeCondition | ScopeCondition | Allow to manage the visibility using advanced conditions |
configuredByAPI | Boolean | Whether this custom field may be configured, updated or deleted only by external API calls, and not manually within the app by an organization user. Setting this flag to true is an equivalent of setting the 3 flags {disableConfiguration, disableOptionConfiguration, disableDeletion} to true. This flag takes precedence over the other flags. |
disableConfiguration | Boolean | Disable the button to configure the custom field within the app |
disableOptionConfiguration | Boolean | Disable the button to configure custom field options (for collection types) within the app |
disableDeletion | Boolean | Disable the button to delete the custom field within the app |
validation | CustomFieldValidation | |
validation.minimumValue | BigDecimal | Only for custom fields of type NUMBER or LONG. The minimum value allowed for this custom field. |
validation.maximumValue | BigDecimal | Only for custom fields of type NUMBER or LONG. The maximum value allowed for this custom field. |
Response body
The updated vehicle custom fields
See CustomField
List custom field options
Fetch the list of options associated with a custom field of type 'LIST'.
Request
GET /api/org/v1/organizations/{organizationId}/custom-options/{listId}
Path variables
parameter | type | required | description |
---|---|---|---|
listId | String | true |
Response body
the list of all options for the specified list id.
field | type | description |
---|---|---|
data | CustomOption[] | |
data[].id | String | This is the unique identifier of the custom option. |
data[].labelsPerLanguage | Map<String,String> | Localized labels of the custom option. Organizations are encouraged to provide labels for each language they manage. |
data[].extra | String | A field to hold extra information about the option, it can hold a complete JSON object. |
data[].accountingCode | String | This is a code, used in accounting exports |
data[].disabled | Boolean | The option may be disabled. It acts as a logical deletion, e.g. existing items still reference the option, but new ones cannot. |
data[].scope | String | scope : the option must be seen by a user, a group or user owning custom field. For user, specify user Id. For group, specify group Id. For user custom field, specify user custom field value. The setup of the custom field is by made by your project manager. Feel free to question him on these options. Optional. |
data[].scopeCondition | ScopeCondition | scopeCondition : the option must be activate on calculated condition. The setup of the custom field is by made by your project manager. Feel free to question him on these options. Optional. |
Update custom field option
Create or update an option in a list of custom options.
Request
POST /api/org/v1/organizations/{organizationId}/custom-options/{listId}/options/{optionId}
Path variables
parameter | type | required | description |
---|---|---|---|
listId | String | true | |
optionId | String | true |
Request body
All data required to create or update the custom option.
field | type | description |
---|---|---|
id | String | This is the unique id of the custom option. Mandatory. |
labelsPerLanguage | Map<String,String> | Localized labels of the custom option. Organizations are encouraged to provide labels for each language they manage. Optional (but highly recommended). |
extra | String | A field to hold extra information about the option, it can hold a complete JSON object. Optional. |
accountingCode | String | Code used in accounting exports. Optional. |
disabled | Boolean | The option may be disabled. It acts as a logical deletion, e.g. existing items still reference the option, but new ones cannot. Optional. |
scope | String | scope : the option must be seen by a user, a group or user owning custom field. For user, specify user Id. For group, specify group Id. For user custom field, specify user custom field value. The setup of the custom field is by made by your project manager. Feel free to question him on these options. Optional. |
scopeCondition | ScopeCondition | scopeCondition : the option must be activate on calculated condition. The setup of the custom field is by made by your project manager. Feel free to question him on these options. Optional. |
Response body
The created or updated option.
See CustomOption
Batch update custom field options
Create or update multiple options in a list of custom options.
Request
PATCH /api/org/v1/organizations/{organizationId}/custom-options/{listId}/options
Path variables
parameter | type | required | description |
---|---|---|---|
listId | String | true |
Request body
A list of data required to create or update each option.
field | type | description |
---|---|---|
id | String | This is the unique id of the custom option. Mandatory. |
labelsPerLanguage | Map<String,String> | Localized labels of the custom option. Organizations are encouraged to provide labels for each language they manage. Optional (but highly recommended). |
extra | String | A field to hold extra information about the option, it can hold a complete JSON object. Optional. |
accountingCode | String | Code used in accounting exports. Optional. |
disabled | Boolean | The option may be disabled. It acts as a logical deletion, e.g. existing items still reference the option, but new ones cannot. Optional. |
scope | String | scope : the option must be seen by a user, a group or user owning custom field. For user, specify user Id. For group, specify group Id. For user custom field, specify user custom field value. The setup of the custom field is by made by your project manager. Feel free to question him on these options. Optional. |
scopeCondition | ScopeCondition | scopeCondition : the option must be activate on calculated condition. The setup of the custom field is by made by your project manager. Feel free to question him on these options. Optional. |
Response body
The list of created or updated options.
field | type | description |
---|---|---|
data | CustomOption[] | |
data[].id | String | This is the unique identifier of the custom option. |
data[].labelsPerLanguage | Map<String,String> | Localized labels of the custom option. Organizations are encouraged to provide labels for each language they manage. |
data[].extra | String | A field to hold extra information about the option, it can hold a complete JSON object. |
data[].accountingCode | String | This is a code, used in accounting exports |
data[].disabled | Boolean | The option may be disabled. It acts as a logical deletion, e.g. existing items still reference the option, but new ones cannot. |
data[].scope | String | scope : the option must be seen by a user, a group or user owning custom field. For user, specify user Id. For group, specify group Id. For user custom field, specify user custom field value. The setup of the custom field is by made by your project manager. Feel free to question him on these options. Optional. |
data[].scopeCondition | ScopeCondition | scopeCondition : the option must be activate on calculated condition. The setup of the custom field is by made by your project manager. Feel free to question him on these options. Optional. |
Delete custom field option
Delete an option from an existing list of custom options.
Be warned that deleting an option referenced by other entities might cause errors. You can safely update an option and disable it to avoid any error.
As deletion is an idempotent operation, deleting a non existing object will not result in an error.Request
DELETE /api/org/v1/organizations/{organizationId}/custom-options/{listId}/options/{optionId}
Path variables
parameter | type | required | description |
---|---|---|---|
listId | String | true | |
optionId | String | true |
Delete all custom field options
Delete all options from an existing list of custom options.
Be warned that deleting an option referenced by other entities might cause errors. You can safely update an option and disable it to avoid any error.
As deletion is an idempotent operation, deleting a non existing object will not result in an error.Request
DELETE /api/org/v1/organizations/{organizationId}/custom-options/{listId}/options
Path variables
parameter | type | required | description |
---|---|---|---|
listId | String | true |
Org. advanced customization
Set of methods to create, update or view expense warning rules of an organization>.
List expense warning rules
curl -X GET "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687/expense-warning-rules" \
-u API_USER_ID:SECRET_KEY \
{
"data" : [ {
"id" : "07b3d1d7-412a-4b47-9e02-290f435e4842",
"type" : "EXTERNAL",
"labels" : {
"en" : "Threshold excess",
"fr" : "Dépassement de seuil"
},
"options" : [ {
"code" : "m30",
"labels" : {
"en" : "Meal over 30€",
"fr" : "Repas au dessus de 30€"
}
}, {
"code" : "m60",
"labels" : {
"en" : "Meal over 60€",
"fr" : "Repas au dessus de 60€"
}
}, {
"code" : "t50",
"labels" : {
"en" : "Taxi over 50€",
"fr" : "Taxi au dessus de 50€"
}
} ],
"externalRuleId" : "my-warning-rule-id"
} ]
}
Fetch the list of expense warning rule
Request
GET /api/org/v1/organizations/{organizationId}/expense-warning-rules
Response body
field | type | description |
---|---|---|
data | WarningRule[] | |
data[].id | String | Unique identifier |
data[].type | WarningRuleType | Rule type, for now only EXTERNAL type can be managed by api |
data[].labels | Map<String,String> | Warning main label |
data[].options | WarningRuleOption[] | Warning rule options. |
data[].disabled | Boolean | Disabled rule. |
data[].externalRuleId | String | The external rule ID (optional) |
Create an expense warning rule
curl -X POST "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687/expense-warning-rules" \
-u API_USER_ID:SECRET_KEY \
-H "Content-Type: application/json" \
--data '{
"labels" : {
"en" : "Threshold excess",
"fr" : "Dépassement de seuil"
},
"options" : [ {
"code" : "m30",
"labels" : {
"en" : "Meal over 30€",
"fr" : "Repas au dessus de 30€"
}
}, {
"code" : "m60",
"labels" : {
"en" : "Meal over 60€",
"fr" : "Repas au dessus de 60€"
}
}, {
"code" : "t50",
"labels" : {
"en" : "Taxi over 50€",
"fr" : "Taxi au dessus de 50€"
}
} ],
"externalRuleId" : "my-warning-rule-id"
}'
{
"id" : "07b3d1d7-412a-4b47-9e02-290f435e4842",
"type" : "EXTERNAL",
"labels" : {
"en" : "Threshold excess",
"fr" : "Dépassement de seuil"
},
"options" : [ {
"code" : "m30",
"labels" : {
"en" : "Meal over 30€",
"fr" : "Repas au dessus de 30€"
}
}, {
"code" : "m60",
"labels" : {
"en" : "Meal over 60€",
"fr" : "Repas au dessus de 60€"
}
}, {
"code" : "t50",
"labels" : {
"en" : "Taxi over 50€",
"fr" : "Taxi au dessus de 50€"
}
} ],
"externalRuleId" : "my-warning-rule-id"
}
Create a single expense warning rule with EXTERNAL type.
Important : created rule will have to be affected to Expenses by API calls exclusively, Jenji will not do any computations to affect it automatically.
Request
POST /api/org/v1/organizations/{organizationId}/expense-warning-rules
Request body
new expense warning rule, you can provide an optional externalRuleId if needed
field | type | description |
---|---|---|
labels | Map<String,String> | Rule labels, en language is required |
options | WarningRuleOption[] | Rule options |
options[].code | String | Technical code for this option (letter, digits, dot, dash and underscore only) |
options[].labels | Map<String,String> | Option labels, en language is required |
type | WarningRuleType | Rule type, default value is EXTERNAL. |
externalRuleId | String | The external rule ID (optional) |
Response body
The created expense warning rule.
See WarningRule
Update an expense warning rule
curl -X PUT "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687/expense-warning-rules/07b3d1d7-412a-4b47-9e02-290f435e4842" \
-u API_USER_ID:SECRET_KEY \
-H "Content-Type: application/json" \
--data '{
"labels" : {
"en" : "Threshold excess",
"fr" : "Dépassement de seuil"
},
"options" : [ {
"code" : "m30",
"labels" : {
"en" : "Meal over 30€",
"fr" : "Repas au dessus de 30€"
}
}, {
"code" : "t50",
"labels" : {
"en" : "Taxi over 50€",
"fr" : "Taxi au dessus de 50€"
}
}, {
"code" : "t150",
"labels" : {
"en" : "Taxi over 150€",
"fr" : "Taxi au dessus de 150€"
}
} ],
"externalRuleId" : "my-warning-rule-id"
}'
{
"id" : "07b3d1d7-412a-4b47-9e02-290f435e4842",
"type" : "EXTERNAL",
"labels" : {
"en" : "Threshold excess",
"fr" : "Dépassement de seuil"
},
"options" : [ {
"code" : "m60",
"labels" : {
"en" : "Meal over 60€",
"fr" : "Repas au dessus de 60€"
}
}, {
"code" : "t150",
"labels" : {
"en" : "Taxi over 150€",
"fr" : "Taxi au dessus de 150€"
}
} ],
"externalRuleId" : "my-warning-rule-id"
}
Update a single expense warning rule.
Request
PUT /api/org/v1/organizations/{organizationId}/expense-warning-rules/{ruleId}
Path variables
parameter | type | required | description |
---|---|---|---|
ruleId | String | true | can be either Jenji ID or an external ID using the format 'ext-your-warning-rule-id' |
Request body
expense warning rule new value
field | type | description |
---|---|---|
labels | Map<String,String> | Rule labels, en language is required |
options | WarningRuleOption[] | Rule options |
options[].code | String | Technical code for this option (letter, digits, dot, dash and underscore only) |
options[].labels | Map<String,String> | Option labels, en language is required |
externalRuleId | String | The external rule ID (optional) |
Response body
The updated expense warning rule.
See WarningRule
Delete an expense warning rule
curl -X DELETE "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687/expense-warning-rules/07b3d1d7-412a-4b47-9e02-290f435e4842" \
-u API_USER_ID:SECRET_KEY \
null
Delete a single expense warning rule.
Request
DELETE /api/org/v1/organizations/{organizationId}/expense-warning-rules/{ruleId}
Path variables
parameter | type | required | description |
---|---|---|---|
ruleId | String | true | can be either Jenji ID or an external ID using the format 'ext-your-warning-rule-id' |
Patch expense warning rules
curl -X PATCH "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687/expense-warning-rules" \
-u API_USER_ID:SECRET_KEY \
-H "Content-Type: application/json" \
--data '[ {
"id" : "07b3d1d7-412a-4b47-9e02-290f435e4842",
"labels" : {
"en" : "Threshold excess",
"fr" : "Dépassement de seuil"
},
"options" : [ {
"code" : "m30",
"labels" : {
"en" : "Meal over 30€",
"fr" : "Repas au dessus de 30€"
}
}, {
"code" : "m60",
"labels" : {
"en" : "Meal over 60€",
"fr" : "Repas au dessus de 60€"
}
}, {
"code" : "t50",
"labels" : {
"en" : "Taxi over 50€",
"fr" : "Taxi au dessus de 50€"
}
} ]
}, {
"labels" : {
"en" : "Weekend expense"
}
}, {
"labels" : {
"en" : "An external warning rule"
},
"externalRuleId" : "my-other-warning-rule-id"
} ]'
{
"data" : [ {
"id" : "07b3d1d7-412a-4b47-9e02-290f435e4842",
"type" : "EXTERNAL",
"labels" : {
"en" : "Threshold excess",
"fr" : "Dépassement de seuil"
},
"options" : [ {
"code" : "m30",
"labels" : {
"en" : "Meal over 30€",
"fr" : "Repas au dessus de 30€"
}
}, {
"code" : "m60",
"labels" : {
"en" : "Meal over 60€",
"fr" : "Repas au dessus de 60€"
}
}, {
"code" : "t50",
"labels" : {
"en" : "Taxi over 50€",
"fr" : "Taxi au dessus de 50€"
}
} ],
"externalRuleId" : "my-warning-rule-id"
}, {
"id" : "7f8812bb-4669-462a-aa51-36c261db8b09",
"type" : "EXTERNAL",
"labels" : {
"en" : "Weekend expense"
}
}, {
"id" : "fb89e175-3df1-4158-90b9-780e04d6b80d",
"type" : "EXTERNAL",
"labels" : {
"en" : "An external warning rule"
},
"externalRuleId" : "my-other-warning-rule-id"
} ]
}
Update or create multiple expense warning rules at once, with EXTERNAL type.
Matching is made on internal or external id, pass a null value in id to create a new rule.
Other existing rules not present in the body will not be updated
Important : created rules will have to be affected to Expenses by API calls exclusively, Jenji will not do any computations to affect them automatically.
Request
PATCH /api/org/v1/organizations/{organizationId}/expense-warning-rules
Request body
expense warning rules new value, you can provide an optional externalRuleId if needed
field | type | description |
---|---|---|
id | String | Existing rule id, if null will create a new rule. If present, it must match an existing rule. |
labels | Map<String,String> | Rule labels, en language is required |
options | WarningRuleOption[] | Rule options |
options[].code | String | Technical code for this option (letter, digits, dot, dash and underscore only) |
options[].labels | Map<String,String> | Option labels, en language is required |
externalRuleId | String | The external rule ID (optional) |
Response body
The updated expense warning rule.
field | type | description |
---|---|---|
data | WarningRule[] | |
data[].id | String | Unique identifier |
data[].type | WarningRuleType | Rule type, for now only EXTERNAL type can be managed by api |
data[].labels | Map<String,String> | Warning main label |
data[].options | WarningRuleOption[] | Warning rule options. |
data[].disabled | Boolean | Disabled rule. |
data[].externalRuleId | String | The external rule ID (optional) |
Organization Users
Set of methods to create, update or view organization users. These methods may only be used by an organization, its bookkeeper, or the master bookkeeper of its bookkeeper.
List all users
curl -X GET "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687/users" \
-u API_USER_ID:SECRET_KEY \
{
"data" : [ {
"id" : "dea2635f-8e3a-482e-9115-ee2ab6dd7b43",
"login" : "john.doe@sample.com",
"email" : "john.doe@sample.com",
"firstName" : "John",
"lastName" : "Doe",
"organizationId" : "74dbaf20-7f22-45e6-8378-cf33cb775687",
"groupId" : "root",
"internalId" : "ABC123",
"customFields" : {
"preferred-number" : 42,
"role" : "director",
"start" : 1522540800000
},
"updatedAt" : "2021-03-15T18:24:36Z",
"createdAt" : "2018-03-15T18:24:36Z",
"profiles" : [ {
"profileId" : "director",
"groupIds" : [ "root" ]
} ],
"mainAccount" : true,
"delegations" : [ {
"id" : "group-id",
"groupId" : "group-id",
"permission" : "WRITE"
}, {
"id" : "user-id",
"userId" : "user-id",
"permission" : "WRITE",
"start" : "2021-12-08",
"end" : "2021-12-15"
} ]
}, {
"id" : "b9ca31e4-71f8-4303-8c14-6e41b3ce8c7a",
"login" : "foo.bar@sample.com",
"email" : "foo.bar@sample.com",
"firstName" : "Foo",
"lastName" : "Bar",
"organizationId" : "74dbaf20-7f22-45e6-8378-cf33cb775687",
"groupId" : "root",
"internalId" : "AZE987",
"customFields" : {
"preferred-number" : 7,
"role" : "driver",
"start" : 1522540800000
},
"vehicles" : [ {
"id" : "150e3fda-2771-48db-8d02-4b4ab2655d30",
"type" : "CAR",
"label" : "CLIO VI",
"taxHorsepower" : 5,
"engineCapacity" : 2946,
"energy" : "PETROL",
"checked" : false
} ],
"updatedAt" : "2021-05-15T18:24:36Z",
"createdAt" : "2018-05-15T18:24:36Z",
"blockedAt" : "2021-05-15T18:24:36Z",
"mainAccount" : true
} ]
}
List all the users of the organization.
Request
GET /api/org/v1/organizations/{organizationId}/users
Query parameters
parameter | type | required | description |
---|---|---|---|
login | String | false | |
internalId | String | false |
Response body
field | type | description |
---|---|---|
data | User[] | |
data[].id | String | Unique identifier of the User in Jenji (UUID or email, depending on the acquisition channel). |
data[].login | String | Login used by the user to authenticate to Jenji. |
data[].email | String | Email address at which the user may be contacted, to receive technical notifications. |
data[].firstName | String | First name of the user, like "Alex" in "Alex Pence". |
data[].lastName | String | Last name of the user, like "Pence" in "Alex Pence". |
data[].organizationId | String | Identifier of the organization to which the user belongs. |
data[].groupId | String | Identifier of the organization group to which the user belongs. |
data[].internalId | String | Identifier of the user in the information system of the organization. |
data[].customFields | Map<String,Object> | Custom fields available specifically for this user, mapped by their key. |
data[].vehicles | Vehicle[] | List of personal vehicles belonging to the user. These vehicles may be referenced in mileage expenses. |
data[].preferredPaymentMethodId | String | Identifier of the preferred payment method of the user, to be selected by default in graphical interfaces. |
data[].preferredCountry | String | Code of the preferred country of the user, to be selected by default in graphical interfaces. |
data[].preferredCurrency | String | Code of the preferred currency of the user, to be selected by default in graphical interfaces. |
data[].preferredDistanceUnit | DistanceUnit | Code of the preferred distance unit of the user. Allowed values are KM and MI, default is KM. |
data[].preferredVehicleId | String | Identifier of the preferred vehicle of the user, to be selected by default in graphical interfaces. |
data[].updatedAt | OffsetDateTime | Timestamp at which the user was last updated. |
data[].createdAt | OffsetDateTime | Timestamp at which the user was created. |
data[].blockedAt | OffsetDateTime | Timestamp at which the user was blocked. This field is null if the user is not blocked. |
data[].profiles | UserProfile[] | List of profiles associated to the user, allowing him/her to work in the expense workflow. |
data[].mainAccount | Boolean | Boolean indicating whether it is the user main/default account. Default is false, unless it is the only account. |
data[].phone | String | The user phone number. |
data[].delegations | Delegation[] | Delegations granted to the user, either on groups, or on other users. |
Get user by ID
curl -X GET "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687/users/b9ca31e4-71f8-4303-8c14-6e41b3ce8c7a" \
-u API_USER_ID:SECRET_KEY \
{
"id" : "b9ca31e4-71f8-4303-8c14-6e41b3ce8c7a",
"login" : "foo.bar@sample.com",
"email" : "foo.bar@sample.com",
"firstName" : "Foo",
"lastName" : "Bar",
"organizationId" : "74dbaf20-7f22-45e6-8378-cf33cb775687",
"groupId" : "root",
"internalId" : "AZE987",
"customFields" : {
"preferred-number" : 7,
"role" : "driver",
"start" : 1522540800000
},
"vehicles" : [ {
"id" : "150e3fda-2771-48db-8d02-4b4ab2655d30",
"type" : "CAR",
"label" : "CLIO VI",
"taxHorsepower" : 5,
"engineCapacity" : 2946,
"energy" : "PETROL",
"checked" : false
} ],
"updatedAt" : "2021-05-15T18:24:36Z",
"createdAt" : "2018-05-15T18:24:36Z",
"blockedAt" : "2021-05-15T18:24:36Z",
"mainAccount" : true
}
Get a user by his ID.
Request
GET /api/org/v1/organizations/{organizationId}/users/{userId}
Response body
An organization user, or simply "user", belongs to a group of the organization. Users work at the different steps of the expense workflow, creating expenses, validating them or authorizing reimbursements.
See User
Create a new user
curl -X POST "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687/users" \
-u API_USER_ID:SECRET_KEY \
-H "Content-Type: application/json" \
--data '{
"login" : "dom.toretto@sample.com",
"email" : "driver@sample.com",
"firstName" : "Dominic",
"lastName" : "Toretto",
"groupId" : "root",
"internalId" : "TFATF",
"profiles" : [ {
"profileId" : "director",
"groupIds" : [ "root" ]
} ],
"customFields" : {
"preferred-number" : 8,
"role" : "driver",
"start" : 1621123200000
},
"mainAccount" : true,
"delegations" : [ {
"userId" : "user-id",
"permission" : "WRITE",
"start" : "2021-12-08",
"end" : "2021-12-15"
}, {
"groupId" : "group-id",
"permission" : "WRITE"
} ]
}'
{
"id" : "b9ca31e4-71f8-4303-8c14-6e41b3ce8c7a",
"login" : "dom.toretto@sample.com",
"email" : "driver@sample.com",
"firstName" : "Dominic",
"lastName" : "Toretto",
"organizationId" : "74dbaf20-7f22-45e6-8378-cf33cb775687",
"groupId" : "root",
"internalId" : "TFATF",
"customFields" : {
"preferred-number" : 8,
"role" : "driver",
"start" : 1621123200000
},
"updatedAt" : "2021-05-15T18:26:36Z",
"createdAt" : "2021-05-15T18:26:36Z",
"profiles" : [ {
"profileId" : "director",
"groupIds" : [ "root" ]
} ],
"mainAccount" : true,
"delegations" : [ {
"id" : "group-id",
"groupId" : "group-id",
"permission" : "WRITE"
}, {
"id" : "user-id",
"userId" : "user-id",
"permission" : "WRITE",
"start" : "2021-12-08",
"end" : "2021-12-15"
} ]
}
Create a new organization user and adds it to a specific group of the organization.
Request
POST /api/org/v1/organizations/{organizationId}/users
Request body
The data required to create the user.
field | type | description |
---|---|---|
login | String | Mandatory. The login of the user, usually his/her email address. Must be unique. |
String | Optional. Email to be used instead of login, if empty login will be used. | |
firstName | String | Optional. First name of the user, like "Alex" in "Alex Pence". |
lastName | String | Optional. Last name of the user, like "Pence" in "Alex Pence". |
language | String | Optional. Code of the primary language of the user (2 characters in lowercase, e.g. "fr" for French). |
preferredPaymentMethodId | String | Optional. Identifier of the preferred payment method of the user. |
preferredCountry | String | Optional. Code of the preferred country of the user (2 characters in uppercase, e.g. FR for France). |
preferredCurrency | String | Optional. Code of the preferred currency of the user (3 characters in uppercase, e.g. EUR for Euro). |
preferredVehicle | String | Optional. Code of the preferred vehicle of the user (vehicleId). |
preferredDistanceUnit | DistanceUnit | Optional. Code of the preferred distance unit of the user (2 characters in uppercase, e.g. KM for Kilometer). Allowed values are KM and MI, default is KM. |
groupId | String | Optional. The organization group in which the user must be created. If left empty, then the user will be added to the root group (same as group id root ). |
internalId | String | Optional. The internal code of the user, in the bookkeeper information system. |
profiles | UserProfile[] | Optional. The profiles to associate to the user. |
customFields | Map<String,Object> | Optional. Custom fields available specifically for this user, mapped by their key. |
mainAccount | Boolean | Optional. Boolean indicating whether it is the main/default user account or not. Default is false, unless it is the only account. If the user already has a main/default account and mainAccount is true, the created user will become the new main account |
phone | String | Optional. The user phone number. |
delegations | Delegation[] | Optional. User or group delegations for the user. |
delegations[].userId | String | Conditional. The identifier of the user on whom the current user is given a delegation. Either the userId or groupId must be filled. |
delegations[].groupId | String | Conditional. The identifier of the group on which the current user is given a delegation. All users of that group may be impersonated. Either the userId or groupId must be filled. |
delegations[].permission | DelegationPermission | Mandatory. The permission type granted by the delegation (read-only, write etc). |
delegations[].start | LocalDate | Conditional. Applies only to user delegations. When filled, end date must be filled as well. The date from which the delegation is valid. |
delegations[].end | LocalDate | Conditional. Applies only to user delegations. When filled, start date must be filled as well. The date after which the delegation ends. |
Response body
The newly-created user, with a unique ID.
See User
Update a user
curl -X PUT "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687/users/{userId}" \
-u API_USER_ID:SECRET_KEY \
-H "Content-Type: application/json" \
--data '{
"email" : "driver@sample.com",
"firstName" : "Dominic",
"lastName" : "Toretto",
"internalId" : "TFATF",
"profiles" : [ {
"profileId" : "director",
"groupIds" : [ "root" ]
} ],
"customFields" : {
"preferred-number" : 9,
"role" : "driver",
"start" : 1621123200000
}
}'
{
"id" : "b9ca31e4-71f8-4303-8c14-6e41b3ce8c7a",
"login" : "dom.toretto@sample.com",
"email" : "driver@sample.com",
"firstName" : "Dominic",
"lastName" : "Toretto",
"organizationId" : "74dbaf20-7f22-45e6-8378-cf33cb775687",
"groupId" : "root",
"internalId" : "TFATF",
"customFields" : {
"preferred-number" : 9,
"role" : "driver",
"start" : 1621123200000
},
"updatedAt" : "2023-03-30T07:50:57.244446Z",
"createdAt" : "2021-05-15T18:26:36Z",
"profiles" : [ {
"profileId" : "director",
"groupIds" : [ "root" ]
} ],
"mainAccount" : true,
"delegations" : [ {
"id" : "group-id",
"groupId" : "group-id",
"permission" : "WRITE"
}, {
"id" : "user-id",
"userId" : "user-id",
"permission" : "WRITE",
"start" : "2021-12-08",
"end" : "2021-12-15"
} ]
}
Update an existing organization user. This is a PUT request, not a PATCH request: any field left empty will be cleared in the end, so make sure you fill in all fields which should have a value when calling this endpoint, paying extra attention to user profiles.
\u26a0\ufe0fBeware that delegations won't be affected, you need to use dedicated endpoints to update a user's delegations.
Request
PUT /api/org/v1/organizations/{organizationId}/users/{userId}
Request body
All data required to update the user.
field | type | description |
---|---|---|
String | Optional. Email to be used instead of login, if empty login will be used. | |
firstName | String | Optional. First name of the user, like "Alex" in "Alex Pence". |
lastName | String | Optional. Last name of the user, like "Pence" in "Alex Pence". |
language | String | Optional. Code of the primary language of the user (2 characters in lowercase, e.g. "fr" for French). |
preferredPaymentMethodId | String | Optional. Identifier of the preferred payment method of the user. |
preferredCountry | String | Optional. Code of the preferred country of the user (2 characters in uppercase, e.g. FR for France). |
preferredCurrency | String | Optional. Code of the preferred currency of the user (3 characters in uppercase, e.g. EUR for Euro). |
preferredVehicle | String | Optional. Code of the preferred vehicle of the user (vehicleId). |
preferredDistanceUnit | DistanceUnit | Optional. Code of the preferred distance unit of the user (2 characters in uppercase, e.g. KM for Kilometer). Allowed values are KM and MI, default is KM. |
groupId | String | Optional.The organization group in which the user must be created. If empty it will be kept as existent. Use root to put the user the root group |
internalId | String | Optional. The internal code of the user, in the bookkeeper information system. |
profiles | UserProfile[] | Optional. The profiles to associate to the user. |
customFields | Map<String,Object> | Optional. Custom fields available specifically for this user, mapped by their key. |
mainAccount | Boolean | Optional. Boolean indicating whether it is the user main/default account or not. Default is false. If the updated user already has a main/default account and mainAccount is true, the updated user will become the new main account |
phone | String | Optional. The user phone number. |
Response body
The updated user.
See User
Update a user login
Request
PATCH /api/org/v1/organizations/{organizationId}/users/{userId}/login
Request body
Updates an existing organization user login.
field | type | description |
---|---|---|
login | String | New login value. |
Response body
An organization user, or simply "user", belongs to a group of the organization. Users work at the different steps of the expense workflow, creating expenses, validating them or authorizing reimbursements.
See User
List all user invitations
curl -X GET "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687/invitations" \
-u API_USER_ID:SECRET_KEY \
{
"data" : [ {
"id" : "903ca6b2-f7e5-4738-ab75-f4e00004e9fb",
"login" : "foo.bar@sample.com",
"email" : "foo.bar@sample.com",
"firstName" : "Foo",
"lastName" : "Bar",
"organizationId" : "74dbaf20-7f22-45e6-8378-cf33cb775687",
"groupId" : "root",
"internalId" : "AZE987",
"customFields" : {
"preferred-number" : 7,
"role" : "driver",
"start" : 1522540800000
},
"delegations" : [ {
"id" : "group-id",
"groupId" : "group-id",
"permission" : "WRITE"
}, {
"id" : "user-id",
"userId" : "user-id",
"permission" : "WRITE",
"start" : "2021-12-08",
"end" : "2021-12-15"
} ]
} ]
}
List all the user invitations of the organization.
Request
GET /api/org/v1/organizations/{organizationId}/invitations
Response body
field | type | description |
---|---|---|
data | UserInvitation[] | |
data[].id | String | Unique identifier of the User invitation in Jenji (UUID). |
data[].login | String | Login used by the user to authenticate to Jenji. |
data[].email | String | Email address at which the user may be contacted, to receive technical notifications. |
data[].firstName | String | First name of the user, like "Alex" in "Alex Pence". |
data[].lastName | String | Last name of the user, like "Pence" in "Alex Pence". |
data[].organizationId | String | Identifier of the organization to which the user belongs. |
data[].groupId | String | Identifier of the organization group to which the user belongs. |
data[].internalId | String | Identifier of the user in the information system of the organization. |
data[].customFields | Map<String,Object> | Custom fields available specifically for this user, mapped by their key. The definitions of custom fields are set on the root group. |
data[].vehicles | Vehicle[] | List of personal vehicles belonging to the user. These vehicles may be referenced in mileage expenses. |
data[].preferredPaymentMethodId | String | Identifier of the preferred payment method of the user, to be selected by default in graphical interfaces. |
data[].preferredCountry | String | Code of the preferred country of the user, to be selected by default in graphical interfaces. |
data[].preferredCurrency | String | Code of the preferred currency of the user, to be selected by default in graphical interfaces. |
data[].state | String | State of the user invitation. The state can be "WAITING", "ACCEPTED" or "DELETED". |
data[].inviteSentAt | OffsetDateTime | Timestamp at which the user invitation was sent. |
data[].createdAt | OffsetDateTime | Timestamp at which the user invitation was created. |
data[].deletedAt | OffsetDateTime | Timestamp at which the user invitation was deleted. This field is null if the user invitation is not deleted. |
data[].profiles | UserProfile[] | List of profiles associated with the user, allowing him/her to work in the expense workflow. |
data[].phone | String | The user phone number. |
data[].delegations | Delegation[] | Delegations to be granted to the user, either on groups, or on other users. |
Create a new user invitation
curl -X POST "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687/invitations" \
-u API_USER_ID:SECRET_KEY \
-H "Content-Type: application/json" \
--data '{
"login" : "foo.bar@sample.com",
"email" : "foo.bar@sample.com",
"firstName" : "Foo",
"lastName" : "Bar",
"groupId" : "root",
"internalId" : "AZE987",
"customFields" : {
"preferred-number" : 7,
"role" : "driver",
"start" : 1522540800000
},
"delegations" : [ {
"groupId" : "group-id",
"permission" : "WRITE"
}, {
"userId" : "user-id",
"permission" : "WRITE",
"start" : "2021-12-08",
"end" : "2021-12-15"
} ]
}'
{
"id" : "4fac84f2-352d-4734-94c7-57d7a158b2cf",
"login" : "foo.bar@sample.com",
"email" : "foo.bar@sample.com",
"firstName" : "Foo",
"lastName" : "Bar",
"organizationId" : "74dbaf20-7f22-45e6-8378-cf33cb775687",
"groupId" : "root",
"internalId" : "AZE987",
"customFields" : {
"preferred-number" : 7,
"role" : "driver",
"start" : 1522540800000
},
"delegations" : [ {
"id" : "group-id",
"groupId" : "group-id",
"permission" : "WRITE"
}, {
"id" : "user-id",
"userId" : "user-id",
"permission" : "WRITE",
"start" : "2021-12-08",
"end" : "2021-12-15"
} ]
}
Create a new user invitation for an organization.
If a user with the same login already exist in the organization, an error will be thrown.
Request
POST /api/org/v1/organizations/{organizationId}/invitations
Request body
The data required to create the user invitation.
field | type | description |
---|---|---|
login | String | Mandatory. The login of the user, usually his/her email address. Must be unique. |
String | Optional. Email to be used instead of login, if empty login will be used. | |
firstName | String | Optional. First name of the user, like "Alex" in "Alex Pence". |
lastName | String | Optional. Last name of the user, like "Pence" in "Alex Pence". |
language | String | Optional. Code of the primary language of the user (2 characters in lowercase, e.g. "fr" for French). |
preferredPaymentMethodId | String | Optional. Identifier of the preferred payment method of the user. |
preferredCountry | String | Optional. Code of the preferred country of the user (2 characters in uppercase, e.g. FR for France). |
preferredCurrency | String | Optional. Code of the preferred currency of the user (3 characters in uppercase, e.g. EUR for Euro). |
groupId | String | Optional. The organization group in which the user must be created. If left empty, then the user will be added to the root group. |
internalId | String | Optional. The internal code of the user, in the bookkeeper information system. |
profiles | UserProfile[] | Optional. The profiles to associate to the user. |
skipMail | Boolean | Optional. Set to true if you do not want the email to be sent. |
customFields | Map<String,Object> | Optional. Custom fields available specifically for this user, mapped by their key. |
phone | String | Optional. The user phone number. |
delegations | Delegation[] | Optional. User or group delegations for the user. |
delegations[].userId | String | Conditional. The identifier of the user on whom the current user is given a delegation. Either the userId or groupId must be filled. |
delegations[].groupId | String | Conditional. The identifier of the group on which the current user is given a delegation. All users of that group may be impersonated. Either the userId or groupId must be filled. |
delegations[].permission | DelegationPermission | Mandatory. The permission type granted by the delegation (read-only, write etc). |
delegations[].start | LocalDate | Conditional. Applies only to user delegations. When filled, end date must be filled as well. The date from which the delegation is valid. |
delegations[].end | LocalDate | Conditional. Applies only to user delegations. When filled, start date must be filled as well. The date after which the delegation ends. |
Response body
The newly-created user invitation, with a unique ID.
See UserInvitation
Block a user
Block a user of the organization. This user will not be able to access Jenji services anymore.
Request
POST /api/org/v1/organizations/{organizationId}/users/{userId}/block
Response body
The blocked user.
See User
Unblock a user
Unblock a user of the organization. This user may access Jenji services again.
Request
POST /api/org/v1/organizations/{organizationId}/users/{userId}/unblock
Response body
The unblocked user.
See User
List all user vehicles
curl -X GET "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687/users/my-user-id/vehicles" \
-u API_USER_ID:SECRET_KEY \
{
"data" : [ {
"id" : "11c15679-53c5-4b17-a92e-3ff7f0988354",
"type" : "CAR",
"label" : "CLIO III",
"taxHorsepower" : 7,
"engineCapacity" : 1149,
"energy" : "PETROL",
"checked" : false
} ]
}
List all vehicles for an organization user.
Request
GET /api/org/v1/organizations/{organizationId}/users/{userId}/vehicles
Response body
field | type | description |
---|---|---|
data | Vehicle[] | |
data[].id | String | Unique identifier of the vehicle in Jenji (UUID). |
data[].type | VehicleType | Type of the vehicle, like a car or a motorcycle. Estimation policies for mileage expenses differ depending on the type. |
data[].label | String | The label of the vehicle, to help the user select the right vehicle when creating an expense. |
data[].taxHorsepower | int | Tax horsepower of the vehicle, used to estimate the expense. |
data[].engineCapacity | Integer | The engine capacity in cubic centimeters (cc). |
data[].energy | VehicleEnergy | The energy used in the vehicle (Petrol, Diesel, Electric, LPG). |
data[].fixedMileageRate | BigDecimal | Fixed mileage reimbursement rate, set by the organization, which overrides official tariffs. |
data[].fixedMileageRateDistanceUnit | DistanceUnit | Fixed mileage reimbursement rate distance unit (km or miles) |
data[].mileageCalculatorId | String | The specific mileage calculator to use when computing mileage expenses for this vehicle. When missing, mileage expenses are computed with the default rules applicable for the organization. |
data[].disabledAt | OffsetDateTime | Timestamp at which the vehicle has been disabled. It may not be used in expenses anymore, but remains in the system for history purposes. |
data[].checked | boolean | Whether the registration document has been verified. |
data[].customFields | Map<String,Object> | Custom fields available specifically for this vehicle, mapped by their key. |
VehicleType
value | description |
---|---|
CAR | |
MOTORCYCLE | |
MOPED | |
BIKE |
VehicleEnergy
Energy for a vehicle. Can be used by some mileage calculators to estimate a mileage expense.
value | description |
---|---|
ELECTRIC | Full electric. Hybrid cars are treated as either petrol or diesel cars for advisory fuel rates. |
PETROL | |
DIESEL | |
LPG | Liquefied Petroleum Gas. |
Create a user vehicle
curl -X POST "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687/users/my-user-id/vehicles" \
-u API_USER_ID:SECRET_KEY \
{
"id" : "11c15679-53c5-4b17-a92e-3ff7f0988354",
"type" : "CAR",
"label" : "CLIO III",
"taxHorsepower" : 7,
"engineCapacity" : 1149,
"energy" : "PETROL",
"checked" : false
}
Add a vehicle for an user.
Request
POST /api/org/v1/organizations/{organizationId}/users/{userId}/vehicles
Request body
A personal vehicle for an organization user. Vehicles are registered to create and estimate mileage expenses, when an organization user travels with his/her personal vehicle, for business.
field | type | description |
---|---|---|
label | String | The label of the vehicle, to help the user select the right vehicle when creating an expense. |
engineCapacity | Integer | Optional. Engine capacity, in cubic centimeters (cc). |
energy | VehicleEnergy | Optional. The energy for the vehicle, one of {PETROL, ELECTRIC, DIESEL, LPG}. Can be used to compute mileage allowances for this vehicle. |
fixedMileageRate | BigDecimal | Fixed mileage reimbursement rate, set by the organization, which overrides official tariffs. |
fixedMileageRateDistanceUnit | DistanceUnit | Fixed mileage reimbursement rate distance unit (km or miles). Default to KM. |
mileageCalculatorId | String | Optional. Identifier of a specific mileage calculator, to be used for this vehicle. If missing, mileage computation use the default rules applicable to the organization. |
disabled | Boolean | Disable the vehicle |
customFields | Map<String,Object> | Custom fields available specifically for this user, mapped by their key. |
type | VehicleType | Type of the vehicle, like a car or a motorcycle. Estimation policies for mileage expenses differ depending on the type. |
taxHorsepower | Integer | Tax horsepower of the vehicle, used to estimate the expense. |
Response body
A personal vehicle for an organization user. Vehicles are registered to create and estimate mileage expenses, when an organization user travels with his/her personal vehicle, for business.
See Vehicle
VehicleEnergy
Energy for a vehicle. Can be used by some mileage calculators to estimate a mileage expense.
value | description |
---|---|
ELECTRIC | Full electric. Hybrid cars are treated as either petrol or diesel cars for advisory fuel rates. |
PETROL | |
DIESEL | |
LPG | Liquefied Petroleum Gas. |
VehicleType
value | description |
---|---|
CAR | |
MOTORCYCLE | |
MOPED | |
BIKE |
Update a user vehicle
curl -X PUT "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687/users/my-user-id/vehicles/{vehicleId}" \
-u API_USER_ID:SECRET_KEY \
{
"id" : "11c15679-53c5-4b17-a92e-3ff7f0988354",
"type" : "CAR",
"label" : "CLIO III",
"taxHorsepower" : 7,
"engineCapacity" : 1149,
"energy" : "PETROL",
"disabledAt" : "2023-03-30T07:50:57.290083Z",
"checked" : false
}
Update a vehicle for an user.
Request
PUT /api/org/v1/organizations/{organizationId}/users/{userId}/vehicles/{vehicleId}
Path variables
parameter | type | required | description |
---|---|---|---|
vehicleId | String | true |
Request body
A personal vehicle for an organization user. Vehicles are registered to create and estimate mileage expenses, when an organization user travels with his/her personal vehicle, for business.
field | type | description |
---|---|---|
label | String | The label of the vehicle, to help the user select the right vehicle when creating an expense. |
engineCapacity | Integer | Optional. Engine capacity, in cubic centimeters (cc). |
energy | VehicleEnergy | Optional. The energy for the vehicle, one of {PETROL, ELECTRIC, DIESEL, LPG}. Can be used to compute mileage allowances for this vehicle. |
fixedMileageRate | BigDecimal | Fixed mileage reimbursement rate, set by the organization, which overrides official tariffs. |
fixedMileageRateDistanceUnit | DistanceUnit | Fixed mileage reimbursement rate distance unit (km or miles). Default to KM. |
mileageCalculatorId | String | Optional. Identifier of a specific mileage calculator, to be used for this vehicle. If missing, mileage computation use the default rules applicable to the organization. |
disabled | Boolean | Disable the vehicle |
customFields | Map<String,Object> | Custom fields available specifically for this user, mapped by their key. |
Response body
A personal vehicle for an organization user. Vehicles are registered to create and estimate mileage expenses, when an organization user travels with his/her personal vehicle, for business.
See Vehicle
VehicleEnergy
Energy for a vehicle. Can be used by some mileage calculators to estimate a mileage expense.
value | description |
---|---|
ELECTRIC | Full electric. Hybrid cars are treated as either petrol or diesel cars for advisory fuel rates. |
PETROL | |
DIESEL | |
LPG | Liquefied Petroleum Gas. |
List all delegations
curl -X GET "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687/users/1f334f06-31c5-4570-bb14-4db791214668/delegations" \
-u API_USER_ID:SECRET_KEY \
{
"data" : [ {
"id" : "group-id",
"groupId" : "group-id",
"permission" : "WRITE"
}, {
"id" : "user-id",
"userId" : "user-id",
"permission" : "WRITE",
"start" : "2021-12-08",
"end" : "2021-12-15"
} ]
}
List all delegations for an organization user.
Request
GET /api/org/v1/organizations/{organizationId}/users/{userId}/delegations
Response body
field | type | description |
---|---|---|
data | Delegation[] | |
data[].id | String | The delegation identifier, autogenerated with user id or group id if not present |
data[].userId | String | The identifier of the user on whom the current user is given a delegation. |
data[].groupId | String | The identifier of the group on which the current user is given a delegation. All users of that group may be impersonated. |
data[].permission | DelegationPermission | The permission type granted by the delegation (read-only, write etc). |
data[].start | LocalDate | The date from which the delegation is valid. Only applies to user delegations. |
data[].end | LocalDate | The date after which the delegation ends. Only applies to user delegations. |
List all user delegations
curl -X GET "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687/users/1f334f06-31c5-4570-bb14-4db791214668/delegations/users" \
-u API_USER_ID:SECRET_KEY \
{
"data" : [ {
"id" : "user-id",
"userId" : "user-id",
"permission" : "WRITE",
"start" : "2021-12-08",
"end" : "2021-12-15"
} ]
}
List all user delegations for an organization user.
Request
GET /api/org/v1/organizations/{organizationId}/users/{userId}/delegations/users
Response body
field | type | description |
---|---|---|
data | Delegation[] | |
data[].id | String | The delegation identifier, autogenerated with user id or group id if not present |
data[].userId | String | The identifier of the user on whom the current user is given a delegation. |
data[].groupId | String | The identifier of the group on which the current user is given a delegation. All users of that group may be impersonated. |
data[].permission | DelegationPermission | The permission type granted by the delegation (read-only, write etc). |
data[].start | LocalDate | The date from which the delegation is valid. Only applies to user delegations. |
data[].end | LocalDate | The date after which the delegation ends. Only applies to user delegations. |
List all group delegations
curl -X GET "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687/users/1f334f06-31c5-4570-bb14-4db791214668/delegations/groups" \
-u API_USER_ID:SECRET_KEY \
{
"data" : [ {
"id" : "group-id",
"groupId" : "group-id",
"permission" : "WRITE"
} ]
}
List all group delegations for an organization user.
Request
GET /api/org/v1/organizations/{organizationId}/users/{userId}/delegations/groups
Response body
field | type | description |
---|---|---|
data | Delegation[] | |
data[].id | String | The delegation identifier, autogenerated with user id or group id if not present |
data[].userId | String | The identifier of the user on whom the current user is given a delegation. |
data[].groupId | String | The identifier of the group on which the current user is given a delegation. All users of that group may be impersonated. |
data[].permission | DelegationPermission | The permission type granted by the delegation (read-only, write etc). |
data[].start | LocalDate | The date from which the delegation is valid. Only applies to user delegations. |
data[].end | LocalDate | The date after which the delegation ends. Only applies to user delegations. |
Update delegations
curl -X PUT "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687/users/1f334f06-31c5-4570-bb14-4db791214668/delegations" \
-u API_USER_ID:SECRET_KEY \
-H "Content-Type: application/json" \
--data '{
"delegations" : [ {
"groupId" : "group-id",
"permission" : "WRITE"
}, {
"userId" : "user-id",
"permission" : "WRITE",
"start" : "2021-12-08",
"end" : "2021-12-15"
} ]
}'
{
"data" : [ {
"id" : "group-id",
"groupId" : "group-id",
"permission" : "WRITE"
}, {
"id" : "user-id",
"userId" : "user-id",
"permission" : "WRITE",
"start" : "2021-12-08",
"end" : "2021-12-15"
} ]
}
Update delegations for a user. Delegations will be completely replaced by the ones passed as parameter, so make sure to provide all delegations for the user (both group and user delegations).
Request
PUT /api/org/v1/organizations/{organizationId}/users/{userId}/delegations
Request body
List of delegations granted to the user. Must contain all delegations for the user.
field | type | description |
---|---|---|
delegations | Delegation[] | List of all delegations to update for the user. When empty, will remove all delegations for the user. |
delegations[].userId | String | Conditional. The identifier of the user on whom the current user is given a delegation. Either the userId or groupId must be filled. |
delegations[].groupId | String | Conditional. The identifier of the group on which the current user is given a delegation. All users of that group may be impersonated. Either the userId or groupId must be filled. |
delegations[].permission | DelegationPermission | Mandatory. The permission type granted by the delegation (read-only, write etc). |
delegations[].start | LocalDate | Conditional. Applies only to user delegations. When filled, end date must be filled as well. The date from which the delegation is valid. |
delegations[].end | LocalDate | Conditional. Applies only to user delegations. When filled, start date must be filled as well. The date after which the delegation ends. |
Response body
field | type | description |
---|---|---|
data | Delegation[] | |
data[].id | String | The delegation identifier, autogenerated with user id or group id if not present |
data[].userId | String | The identifier of the user on whom the current user is given a delegation. |
data[].groupId | String | The identifier of the group on which the current user is given a delegation. All users of that group may be impersonated. |
data[].permission | DelegationPermission | The permission type granted by the delegation (read-only, write etc). |
data[].start | LocalDate | The date from which the delegation is valid. Only applies to user delegations. |
data[].end | LocalDate | The date after which the delegation ends. Only applies to user delegations. |
Update user delegations
curl -X PUT "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687/users/1f334f06-31c5-4570-bb14-4db791214668/delegations/users" \
-u API_USER_ID:SECRET_KEY \
-H "Content-Type: application/json" \
--data '{
"delegations" : [ {
"userId" : "user-id",
"permission" : "WRITE",
"start" : "2021-12-08",
"end" : "2021-12-15"
} ]
}'
{
"data" : [ {
"id" : "user-id",
"userId" : "user-id",
"permission" : "WRITE",
"start" : "2021-12-08",
"end" : "2021-12-15"
} ]
}
Update user delegations for a user. Delegations will be completely replaced by the ones passed as parameter, so make sure to provide all user delegations for the user.
Request
PUT /api/org/v1/organizations/{organizationId}/users/{userId}/delegations/users
Request body
List of delegations granted to the user. Must contain all delegations for the user.
field | type | description |
---|---|---|
delegations | Delegation[] | List of all delegations to update for the user. When empty, will remove all delegations for the user. |
delegations[].userId | String | Conditional. The identifier of the user on whom the current user is given a delegation. Either the userId or groupId must be filled. |
delegations[].groupId | String | Conditional. The identifier of the group on which the current user is given a delegation. All users of that group may be impersonated. Either the userId or groupId must be filled. |
delegations[].permission | DelegationPermission | Mandatory. The permission type granted by the delegation (read-only, write etc). |
delegations[].start | LocalDate | Conditional. Applies only to user delegations. When filled, end date must be filled as well. The date from which the delegation is valid. |
delegations[].end | LocalDate | Conditional. Applies only to user delegations. When filled, start date must be filled as well. The date after which the delegation ends. |
Response body
field | type | description |
---|---|---|
data | Delegation[] | |
data[].id | String | The delegation identifier, autogenerated with user id or group id if not present |
data[].userId | String | The identifier of the user on whom the current user is given a delegation. |
data[].groupId | String | The identifier of the group on which the current user is given a delegation. All users of that group may be impersonated. |
data[].permission | DelegationPermission | The permission type granted by the delegation (read-only, write etc). |
data[].start | LocalDate | The date from which the delegation is valid. Only applies to user delegations. |
data[].end | LocalDate | The date after which the delegation ends. Only applies to user delegations. |
Update group delegations
curl -X PUT "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687/users/1f334f06-31c5-4570-bb14-4db791214668/delegations/groups" \
-u API_USER_ID:SECRET_KEY \
-H "Content-Type: application/json" \
--data '{
"delegations" : [ {
"groupId" : "group-id",
"permission" : "WRITE"
} ]
}'
{
"data" : [ {
"id" : "group-id",
"groupId" : "group-id",
"permission" : "WRITE"
} ]
}
Update group delegations for a user. Delegations will be completely replaced by the ones passed as parameter, so make sure to provide all group delegations for the user.
Request
PUT /api/org/v1/organizations/{organizationId}/users/{userId}/delegations/groups
Request body
List of delegations granted to the user. Must contain all delegations for the user.
field | type | description |
---|---|---|
delegations | Delegation[] | List of all delegations to update for the user. When empty, will remove all delegations for the user. |
delegations[].userId | String | Conditional. The identifier of the user on whom the current user is given a delegation. Either the userId or groupId must be filled. |
delegations[].groupId | String | Conditional. The identifier of the group on which the current user is given a delegation. All users of that group may be impersonated. Either the userId or groupId must be filled. |
delegations[].permission | DelegationPermission | Mandatory. The permission type granted by the delegation (read-only, write etc). |
delegations[].start | LocalDate | Conditional. Applies only to user delegations. When filled, end date must be filled as well. The date from which the delegation is valid. |
delegations[].end | LocalDate | Conditional. Applies only to user delegations. When filled, start date must be filled as well. The date after which the delegation ends. |
Response body
field | type | description |
---|---|---|
data | Delegation[] | |
data[].id | String | The delegation identifier, autogenerated with user id or group id if not present |
data[].userId | String | The identifier of the user on whom the current user is given a delegation. |
data[].groupId | String | The identifier of the group on which the current user is given a delegation. All users of that group may be impersonated. |
data[].permission | DelegationPermission | The permission type granted by the delegation (read-only, write etc). |
data[].start | LocalDate | The date from which the delegation is valid. Only applies to user delegations. |
data[].end | LocalDate | The date after which the delegation ends. Only applies to user delegations. |
Expenses
Set of methods to create, update or query expenses. These methods may only be called by the organization for its own expenses, or by its bookkeeper.
Search expenses of an organization
curl -X POST "https://api-test.jenji.io/api/org/v1/organizations/74dbaf20-7f22-45e6-8378-cf33cb775687/expenses/search" \
-u API_USER_ID:SECRET_KEY \
-H "Content-Type: application/json" \
--data '{
"searchMode" : "TIME",
"start" : "2020-12-20",
"end" : "2020-12-24",
"states" : [ ],
"includeDeleted" : false
}'
{
"data" : [ {
"id" : "e02cbf8a-b0ea-4464-8823-3f981532648b",
"userId" : "test@domain.com",
"organizationId" : "74dbaf20-7f22-45e6-8378-cf33cb775687",
"time" : "2020-12-20",
"total" : 7.11,
"currency" : "EUR",
"country" : "FR",
"billable" : false,
"state" : "WAITING_FOR_VALIDATION",
"label" : "Burrito",
"customFields" : {
"" : ""
},
"createdAt" : "2021-02-19T09:51:20.000000987Z",
"createdWith" : "api/v1",
"category" : "lunch",
"receiptKey" : "test@domain.com/f1e533b8-d6e8-4796-a102-37a6310dc925.jpg",
"paymentMethodId" : "8288ac38-8d04-484c-89ab-6bee22e8b602",
"totalWithoutTax" : 5.93,
"taxes" : [ {
"baseAmount" : 5.93,
"rate" : 20,
"amount" : 1.19
} ],
"type" : "STANDARD"
}, {
"id" : "c4c25f1f-891e-42f6-aff0-920229b311d1",
"userId" : "test@domain.com",
"organizationId" : "74dbaf20-7f22-45e6-8378-cf33cb775687",
"time" : "2020-12-24",
"total" : 340.58,
"currency" : "EUR",
"country" : "FR",
"billable" : false,
"state" : "WAITING_FOR_VALIDATION",
"label" : "Rouen Paris",
"createdAt" : "2021-02-24T15:42:54.000000987Z",
"createdWith" : "android/sdk-1.6.0",
"distance" : 324,
"vehicleId" : "7a1da677-3bc3-4a60-8941-b4e48a3ec239",
"type" : "MILEAGE"
} ]
}
Search for expenses for an organization, according to specified criteria. Returned expenses may be of different types, like standard or mileage expenses.
Request
POST /api/org/v1/organizations/{organizationId}/expenses/search
Request body
The criteria to search for.
field | type | description |
---|---|---|
searchMode | SEARCH_MODE | Mandatory if you specify a period. Determines which date to search on (creation or imputation). Default value is TIME (imputation). |
start | LocalDate | Mandatory if you specify a period. Inclusive start of the search interval as a local date (YYYY-MM-DD). |
end | LocalDate | Mandatory if you specify a period. Inclusive end of the search interval as a local date (YYYY-MM-DD). |
states | String[] | Optional. List of states to match when searching expenses. Possible states include: 'ACCEPTED', 'WAITING_FOR_VALIDATION', 'EXPORTED', 'ACCOUNTED', 'PAID'. |
includeDeleted | Boolean | Optional. Whether to include deleted expenses in the search. False when not specified. |
Response body
List of expenses matching the search criteria.
field | type | description |
---|---|---|
data | Expense[] | |
data[].id | String | Unique identifier of the expense in Jenji (a UUID). |
data[].userId | String | Unique identifier of the organization user for which the expense applies (either an email or a UUID, depending on the acquisition channel). |
data[].organizationId | String | Unique identifier of the organization to which the expense user belongs. This identifier is determined by the routing rules declared for the organization, and is set right after the expense creation. |
data[].time | LocalDate | Day on which the expense occurred (imputation). |
data[].explanation | String | Explanation for the expense, provided by the user who has created the expense. This explanation will be read by the manager who approves the expense. |
data[].tags | String[] | Simple labels, freely settable by the user who creates the expense. Tags may be used to search and find expenses easily in the various front clients (web application, mobile applications). |
data[].total | BigDecimal | The total amount of the expense, including taxes. |
data[].currency | String | The currency of the total amount. This currency should match the one specified in the receipt, when there is a receipt available. |
data[].country | String | The country in which the expense occurred. |
data[].billable | Boolean | Whether the expense may be billed to another party. |
data[].reimbursable | Boolean | Whether the expense may be reimbursed to the user who has created it. |
data[].attendees | String[] | The expense may be related to an event to which many users of the organization have attended. In such cases, the list of attendees contain the identifiers or these users. |
data[].state | String | The state the expense is in, when the query is performed. The state may vary across organizations, depending on whether they have defined a custom workflow for expense management. |
data[].label | String | The vendor of the service for which the expense has occurred (e.g. the name of a restaurant, a taxi company...). |
data[].customFields | Map<String,Object> | Custom fields are defined by organizations, to help classify an expense for analytic purposes. This fields maps values for all required custom fields. |
data[].reimbursement | Reimbursement | Contains all the details of the reimbursement of the expense to the user. This field is only set after the expense has been validated. |
data[].createdAt | OffsetDateTime | Timestamp at which the expense was created. |
data[].createdWith | String | Medium through which the expense was created (mobile phone, web service...). |
data[].updatedAt | OffsetDateTime | Timestamp at which the expense was last updated. |
data[].validatedBy | String | Identifier of the user who has validated the expense (standard workflow). |
data[].validatedAt | OffsetDateTime | Timestamp at which the expense was validated (standard workflow). |
data[].accountedBy | String | Identifier of the user who has exported the expense for accounting (standard workflow). |
data[].accountedAt | OffsetDateTime | Timestamp at which the expense was accounted for (standard workflow). |
data[].paidBy | String | Identifier of the user who has authorized the reimbursement of the expense (standard workflow). |
data[].paidAt | OffsetDateTime | Timestamp at which the expense was reimbursed to the user (standard workflow). |
data[].checkedBy | String | Identifier of the user who has checked the expense (standard workflow). |
data[].checkedAt | OffsetDateTime | Timestamp at which the expense was checked (standard workflow). |
data[].deletedBy | String | Identifier of the user who has deleted the expense (standard workflow). |
data[].deletedAt | OffsetDateTime | Timestamp at which the expense was deleted (standard workflow). |
data[].warnings | ExpenseWarning[] | List of the expense warnings (duplicate, invalid receipt...). |
data[].lastAction | String | |
data[].lastActionBy | String | |
data[].lastActionAt | OffsetDateTime | |
data[].lastActionComment | String | |
data[].type | ExpenseType |
SEARCH_MODE
Determines which date the search interval applies to.
value | description |
---|---|
TIME | Apply the search interval to the imputation date of expenses. |
CREATION | Apply the search interval to the creation date of expenses. |
Search expenses of your organization
curl -X POST "https://api-test.jenji.io/api/org/v1/expenses/search" \
-u API_USER_ID:SECRET_KEY \
-H "Content-Type: application/json" \
--data '{
"searchMode" : "TIME",
"start" : "2020-12-20",
"end" : "2020-12-24",
"states" : [ ],
"includeDeleted" : false
}'
{
"data" : [ ]
}
Search for expenses of your own organization (as a root admin), according to specified criteria. Returned expenses may be of different types, like standard or mileage expenses.
Request
POST /api/org/v1/expenses/search
Request body
The criteria to search for.
field | type | description |
---|---|---|
searchMode | SEARCH_MODE | Mandatory if you specify a period. Determines which date to search on (creation or imputation). Default value is TIME (imputation). |
start | LocalDate | Mandatory if you specify a period. Inclusive start of the search interval as a local date (YYYY-MM-DD). |
end | LocalDate | Mandatory if you specify a period. Inclusive end of the search interval as a local date (YYYY-MM-DD). |
states | String[] | Optional. List of states to match when searching expenses. Possible states include: 'ACCEPTED', 'WAITING_FOR_VALIDATION', 'EXPORTED', 'ACCOUNTED', 'PAID'. |
includeDeleted | Boolean | Optional. Whether to include deleted expenses in the search. False when not specified. |
Response body
List of expenses matching the search criteria.
field | type | description |
---|---|---|
data | Expense[] | |
data[].id | String | Unique identifier of the expense in Jenji (a UUID). |
data[].userId | String | Unique identifier of the organization user for which the expense applies (either an email or a UUID, depending on the acquisition channel). |
data[].organizationId | String | Unique identifier of the organization to which the expense user belongs. This identifier is determined by the routing rules declared for the organization, and is set right after the expense creation. |
data[].time | LocalDate | Day on which the expense occurred (imputation). |
data[].explanation | String | Explanation for the expense, provided by the user who has created the expense. This explanation will be read by the manager who approves the expense. |
data[].tags | String[] | Simple labels, freely settable by the user who creates the expense. Tags may be used to search and find expenses easily in the various front clients (web application, mobile applications). |
data[].total | BigDecimal | The total amount of the expense, including taxes. |
data[].currency | String | The currency of the total amount. This currency should match the one specified in the receipt, when there is a receipt available. |
data[].country | String | The country in which the expense occurred. |
data[].billable | Boolean | Whether the expense may be billed to another party. |
data[].reimbursable | Boolean | Whether the expense may be reimbursed to the user who has created it. |
data[].attendees | String[] | The expense may be related to an event to which many users of the organization have attended. In such cases, the list of attendees contain the identifiers or these users. |
data[].state | String | The state the expense is in, when the query is performed. The state may vary across organizations, depending on whether they have defined a custom workflow for expense management. |
data[].label | String | The vendor of the service for which the expense has occurred (e.g. the name of a restaurant, a taxi company...). |
data[].customFields | Map<String,Object> | Custom fields are defined by organizations, to help classify an expense for analytic purposes. This fields maps values for all required custom fields. |
data[].reimbursement | Reimbursement | Contains all the details of the reimbursement of the expense to the user. This field is only set after the expense has been validated. |
data[].createdAt | OffsetDateTime | Timestamp at which the expense was created. |
data[].createdWith | String | Medium through which the expense was created (mobile phone, web service...). |
data[].updatedAt | OffsetDateTime | Timestamp at which the expense was last updated. |
data[].validatedBy | String | Identifier of the user who has validated the expense (standard workflow). |
data[].validatedAt | OffsetDateTime | Timestamp at which the expense was validated (standard workflow). |
data[].accountedBy | String | Identifier of the user who has exported the expense for accounting (standard workflow). |
data[].accountedAt | OffsetDateTime | Timestamp at which the expense was accounted for (standard workflow). |
data[].paidBy | String | Identifier of the user who has authorized the reimbursement of the expense (standard workflow). |
data[].paidAt | OffsetDateTime | Timestamp at which the expense was reimbursed to the user (standard workflow). |
data[].checkedBy | String | Identifier of the user who has checked the expense (standard workflow). |
data[].checkedAt | OffsetDateTime | Timestamp at which the expense was checked (standard workflow). |
data[].deletedBy | String | Identifier of the user who has deleted the expense (standard workflow). |
data[].deletedAt | OffsetDateTime | Timestamp at which the expense was deleted (standard workflow). |
data[].warnings | ExpenseWarning[] | List of the expense warnings (duplicate, invalid receipt...). |
data[].lastAction | String | |
data[].lastActionBy | String | |
data[].lastActionAt | OffsetDateTime | |
data[].lastActionComment | String | |
data[].type | ExpenseType |
SEARCH_MODE
Determines which date the search interval applies to.
value | description |
---|---|
TIME | Apply the search interval to the imputation date of expenses. |
CREATION | Apply the search interval to the creation date of expenses. |
View an expense
curl -X GET "https://api-test.jenji.io/api/org/v1/expenses/e02cbf8a-b0ea-4464-8823-3f981532648b" \
-u API_USER_ID:SECRET_KEY \
{
"id" : "e02cbf8a-b0ea-4464-8823-3f981532648b",
"userId" : "test@domain.com",
"organizationId" : "74dbaf20-7f22-45e6-8378-cf33cb775687",
"time" : "2020-12-20",
"total" : 7.11,
"currency" : "EUR",
"country" : "FR",
"billable" : false,
"state" : "WAITING_FOR_VALIDATION",
"label" : "Burrito",
"customFields" : {
"" : ""
},
"createdAt" : "2021-02-19T09:51:20.000000987Z",
"createdWith" : "api/v1",
"category" : "lunch",
"receiptKey" : "test@domain.com/3dd6cdf0-8546-4daf-91a1-2c116d4a19bd.jpg",
"paymentMethodId" : "8288ac38-8d04-484c-89ab-6bee22e8b602",
"totalWithoutTax" : 5.93,
"taxes" : [ {
"baseAmount" : 5.93,
"rate" : 20,
"amount" : 1.19
} ],
"type" : "STANDARD"
}
Look up an expense by its identifier.
Request
GET /api/org/v1/expenses/{expenseId}
Response body
The expense.
See Expense
Create a new expense
curl -X POST "https://api-test.jenji.io/api/org/v1/expenses" \
-u API_USER_ID:SECRET_KEY \
-H "Content-Type: application/json" \
--data '{
"type" : "STANDARD",
"time" : "2020-12-20",
"billable" : false,
"customFields" : {
"" : ""
},
"taxes" : [ {
"baseAmount" : 5.93,
"rate" : 20,
"amount" : 1.19
} ],
"country" : "FR",
"label" : "Burrito",
"category" : "lunch",
"currency" : "EUR",
"total" : 7.11,
"totalWithoutTax" : 5.93,
"paymentMethodId" : "8288ac38-8d04-484c-89ab-6bee22e8b602",
"receiptKey" : "test@domain.com/9f7ad0c5-6b43-4d58-9f6a-9d1be1e6b1af.jpg",
"userId" : "test@domain.com",
"type" : "STANDARD"
}'
{
"id" : "e02cbf8a-b0ea-4464-8823-3f981532648b",
"userId" : "test@domain.com",
"organizationId" : "74dbaf20-7f22-45e6-8378-cf33cb775687",
"time" : "2020-12-20",
"total" : 7.11,
"currency" : "EUR",
"country" : "FR",
"billable" : false,
"state" : "WAITING_FOR_VALIDATION",
"label" : "Burrito",
"customFields" : {
"" : ""
},
"createdAt" : "2021-02-19T09:51:20.000000987Z",
"createdWith" : "api/v1",
"category" : "lunch",
"receiptKey" : "test@domain.com/9f7ad0c5-6b43-4d58-9f6a-9d1be1e6b1af.jpg",
"paymentMethodId" : "8288ac38-8d04-484c-89ab-6bee22e8b602",
"totalWithoutTax" : 5.93,
"taxes" : [ {
"baseAmount" : 5.93,
"rate" : 20,
"amount" : 1.19
} ],
"type" : "STANDARD"
}
curl -X POST "https://api-test.jenji.io/api/org/v1/expenses?check-missing-custom-fields=true" \
-u API_USER_ID:SECRET_KEY \
-H "Content-Type: application/json" \
--data '{
"type" : "STANDARD",
"time" : "2020-12-20",
"billable" : false,
"customFields" : { },
"taxes" : [ {
"baseAmount" : 5.93,
"rate" : 20,
"amount" : 1.19
} ],
"country" : "FR",
"label" : "Burrito",
"category" : "lunch",
"currency" : "EUR",
"total" : 7.11,
"totalWithoutTax" : 5.93,
"paymentMethodId" : "8288ac38-8d04-484c-89ab-6bee22e8b602",
"receiptKey" : "test@domain.com/c5acc803-40d7-458d-a972-a12e6a056640.jpg",
"userId" : "test@domain.com",
"type" : "STANDARD"
}'
{
"timestamp" : 1680162657405,
"error" : "Missing custom field",
"path" : "/api/org/v1/expenses",
"errorCode" : "EXP_033",
"status" : 400
}
Create a new expense, based on the provided expense data.
Request
POST /api/org/v1/expenses
Query parameters
parameter | type | required | description |
---|---|---|---|
check-missing-custom-fields | Boolean | false | Enforce presence of all custom fields required for validation (default: false) |
Request body
Expense data.
3 variants:
CreateStandardExpense
Creates a new standard expense, with a receipt.
field | type | description |
---|---|---|
time | LocalDate | Mandatory. The day on which the expense occurred (yyyy-MM-dd). |
explanation | String | Optional. Any comment by the user, explaining in what context the expense occurred. |
billable | Boolean | Optional. Whether the expense may be billed to another party. |
tags | String[] | Optional. List of tags selected by the user, to associate to the expense. These tags may be used in graphical agents to search for expenses. |
customFields | Map<String,Object> | Optional. Map of custom field values, by custom field code. You must ensure that the type of the custom field value is consistent with the type of the custom field definition, recorded on the organization. |
taxes | Tax[] | Optional. Details of the taxes, when taxes apply only on parts of the total amount. |
attendees | String[] | Optional. List of identifiers of organization users who also participated in the event. The current user pays for all of them. |
country | String | Mandatory. Code of the country of the expense, a standard two-letter code in uppercase (e.g.: FR). |
label | String | Mandatory. The vendor of the service for which the expense has occurred (e.g. the name of a restaurant, a taxi company...). |
category | String | Mandatory. The category to which the expense belongs. |
currency | String | Mandatory. Code of the currency of the expense, a standard three-letter code in uppercase (e.g.: EUR). |
total | BigDecimal | Mandatory. The total with taxes reported on the receipt. Note that the amount must have correct decimal places in relation to its currency. |
totalWithoutTax | BigDecimal | Optional. The total without taxes reported on the receipt. Note that the amount must have correct decimal places in relation to its currency. |
paymentMethodId | String | Mandatory. The payment method used by the organization user to pay for the expense. It must be declared on the organization itself. |
reimbursable | Boolean | Optional. Whether the expense may be reimbursed. |
receiptKey | String | Mandatory. The key of the receipt, obtained when uploading the receipt to the Jenji Storage. Once the receipt has been uploaded, it may not be changed. |
userId | String | Mandatory. The user who registers an expense, and expects a reimbursement. |
type | ExpenseType | Mandatory. Type of the expense. |
CreateMileageExpense
Creates a new mileage expense, for users traveling for business, with their personal vehicle.
field | type | description |
---|---|---|
time | LocalDate | Mandatory. The day on which the expense occurred (yyyy-MM-dd). |
explanation | String | Optional. Any comment by the user, explaining in what context the expense occurred. |
billable | Boolean | Optional. Whether the expense may be billed to another party. |
tags | String[] | Optional. List of tags selected by the user, to associate to the expense. These tags may be used in graphical agents to search for expenses. |
customFields | Map<String,Object> | Optional. Map of custom field values, by custom field code. You must ensure that the type of the custom field value is consistent with the type of the custom field definition, recorded on the organization. |
label | String | Mandatory. The description of the travel. |
country | String | Mandatory. Code of the country of the expense, a standard two-letter code in uppercase (e.g.: FR). |
reimbursable | Boolean | Optional. Whether the expense may be reimbursed. |
distance | BigDecimal | Mandatory. The distance travelled by the user. The amount to reimburse is usually calculated with the distance. |
computedDistance | BigDecimal | The distance computed by Google Maps. |
distanceUnit | DistanceUnit | Optional. The distance unit for the mileage, default is KM. |
numberOfPassengers | Integer | Optional. Number of passengers transported by a user, on a trip. Some mileage allowances may include a premium on the amount reimbursed to the user, when there are some passengers. |
vehicleId | String | Mandatory. The identifier of the personal vehicle of the user, defined in his/her profile. |
waypoints | Waypoint[] | Optional. The waypoints describe the different points of the journey made by the user. |
total | BigDecimal | Optional. Amount of the expense, if not null will force the mileage total to this value instead of computing it with Jenji\u2019s system. |
userId | String | Mandatory. The user who registers an expense, and expects a reimbursement. |
type | ExpenseType | Mandatory. Type of the expense. |
CreateAllowanceExpense
Creates an expense of type allowance. An allowance is an expense which amount (among other things) is fixed, based on company rules. For instance, one may receive an allowance of 15\u20ac for lunches.
field | type | description |
---|---|---|
time | LocalDate | Mandatory. The day on which the expense occurred (yyyy-MM-dd). |
explanation | String | Optional. Any comment by the user, explaining in what context the expense occurred. |
billable | Boolean | Optional. Whether the expense may be billed to another party. |
tags | String[] | Optional. List of tags selected by the user, to associate to the expense. These tags may be used in graphical agents to search for expenses. |
customFields | Map<String,Object> | Optional. Map of custom field values, by custom field code. You must ensure that the type of the custom field value is consistent with the type of the custom field definition, recorded on the organization. |
taxes | Tax[] | Optional. Details of the taxes, when taxes apply only on parts of the total amount. |
attendees | String[] | Optional. List of identifiers of organization users who also participated in the event. The current user pays for all of them. |
country | String | Optional. Code of the country of the expense, a standard two-letter code in uppercase (e.g.: FR). May be filled only if the value is not set on the allowance template. |
label | String | Optional. The vendor of the service for which the expense has occurred (e.g. the name of a restaurant, a taxi company...). May be filled only if the value is not set on the allowance template. |
category | String | Optional. The category to which the expense belongs. May be filled only if the value is not set on the allowance template. |
paymentMethodId | String | Optional. The payment method used by the organization user to pay for the expense. It must be declared on the organization itself. May be filled only if the value is not set on the allowance template. |
templateId | String | Mandatory. The identifier of the template used by the allowance to derive default fields on the expense. After the template has been set, it may not be changed. |
userId | String | Mandatory. The user who registers an expense, and expects a reimbursement. |
type | ExpenseType | Mandatory. Type of the expense. |
Response body
The newly-created expense.
See Expense
Update an expense
curl -X PUT "https://api-test.jenji.io/api/org/v1/expenses/e02cbf8a-b0ea-4464-8823-3f981532648b" \
-u API_USER_ID:SECRET_KEY \
-H "Content-Type: application/json" \
--data '{
"type" : "STANDARD",
"time" : "2020-12-20",
"billable" : false,
"customFields" : {
"" : ""
},
"taxes" : [ {
"baseAmount" : 5.93,
"rate" : 20,
"amount" : 1.19
} ],
"country" : "FR",
"label" : "Burrito",
"category" : "lunch",
"currency" : "EUR",
"total" : 7.11,
"totalWithoutTax" : 5.93,
"paymentMethodId" : "8288ac38-8d04-484c-89ab-6bee22e8b602",
"type" : "STANDARD"
}'
{
"id" : "e02cbf8a-b0ea-4464-8823-3f981532648b",
"userId" : "test@domain.com",
"organizationId" : "74dbaf20-7f22-45e6-8378-cf33cb775687",
"time" : "2020-12-20",
"total" : 7.11,
"currency" : "EUR",
"country" : "FR",
"billable" : false,
"state" : "WAITING_FOR_VALIDATION",
"label" : "Burrito",
"customFields" : {
"" : ""
},
"createdAt" : "2021-02-19T09:51:20.000000987Z",
"createdWith" : "api/v1",
"category" : "lunch",
"receiptKey" : "test@domain.com/47eb5d3e-696e-4f34-87cc-b0806422c9d0.jpg",
"paymentMethodId" : "8288ac38-8d04-484c-89ab-6bee22e8b602",
"totalWithoutTax" : 5.93,
"taxes" : [ {
"baseAmount" : 5.93,
"rate" : 20,
"amount" : 1.19
} ],
"type" : "STANDARD"
}
Update the fields of an expense. Updates may only be performed if the state of the expense allows it. This is a PUT request, not a PATCH request: any field left empty will be cleared in the end, so make sure you fill in all fields which should have a value when calling this endpoint.
Request
PUT /api/org/v1/expenses/{expenseId}
Query parameters
parameter | type | required | description |
---|---|---|---|
check-missing-custom-fields | Boolean | false | Enforce presence of all custom fields required for validation (default: false) |
Request body
Expense data.
3 variants:
UpdateStandardExpense
Updates an existing standard expense. You may not change the receipt for legal reasons: if an organization user has uploaded the wrong receipt, then you must cancel the current expense and re-create a new one.
field | type | description |
---|---|---|
time | LocalDate | Mandatory. The day on which the expense occurred (yyyy-MM-dd). |
explanation | String | Optional. Any comment by the user, explaining in what context the expense occurred. |
billable | Boolean | Optional. Whether the expense may be billed to another party. |
tags | String[] | Optional. List of tags selected by the user, to associate to the expense. These tags may be used in graphical agents to search for expenses. |
customFields | Map<String,Object> | Optional. Map of custom field values, by custom field code. You must ensure that the type of the custom field value is consistent with the type of the custom field definition, recorded on the organization. |
taxes | Tax[] | Optional. Details of the taxes, when taxes apply only on parts of the total amount. |
attendees | String[] | Optional. List of identifiers of organization users who also participated in the event. The current user pays for all of them. |
country | String | Mandatory. Code of the country of the expense, a standard two-letter code in uppercase (e.g.: FR). |
label | String | Mandatory. The vendor of the service for which the expense has occurred (e.g. the name of a restaurant, a taxi company...). |
category | String | Mandatory. The category to which the expense belongs. |
currency | String | Mandatory. Code of the currency of the expense, a standard three-letter code in uppercase (e.g.: EUR). |
total | BigDecimal | Mandatory. The total with taxes reported on the receipt. Note that the amount must have correct decimal places in relation to its currency. |
totalWithoutTax | BigDecimal | Optional. The total without taxes reported on the receipt. Note that the amount must have correct decimal places in relation to its currency. |
paymentMethodId | String | Mandatory. The payment method used by the organization user to pay for the expense. It must be declared on the organization itself. |
reimbursable | Boolean | Optional. Whether the expense may be reimbursed. |
actionUserId | String | Optional. Identifier of the user who updates the expense. This user must belong to the same organization as the one of the user who declared the expense. If not filled in, then the action maker becomes the user associated to the API token. |
type | ExpenseType | Mandatory. Type of the expense. |
UpdateMileageExpense
Updates an existing mileage expense, for users traveling for business, with their personal vehicle.
field | type | description |
---|---|---|
time | LocalDate | Mandatory. The day on which the expense occurred (yyyy-MM-dd). |
explanation | String | Optional. Any comment by the user, explaining in what context the expense occurred. |
billable | Boolean | Optional. Whether the expense may be billed to another party. |
tags | String[] | Optional. List of tags selected by the user, to associate to the expense. These tags may be used in graphical agents to search for expenses. |
customFields | Map<String,Object> | Optional. Map of custom field values, by custom field code. You must ensure that the type of the custom field value is consistent with the type of the custom field definition, recorded on the organization. |
label | String | Mandatory. The description of the travel. |
country | String | Mandatory. Code of the country of the expense, a standard two-letter code in uppercase (e.g.: FR). |
reimbursable | Boolean | Optional. Whether the expense may be reimbursed. |
distance | BigDecimal | Mandatory. The distance travelled by the user. The amount to reimburse is usually calculated with the distance. |
computedDistance | BigDecimal | The distance computed by Google Maps. |
distanceUnit | DistanceUnit | Optional. The distance unit for the mileage, default is KM. |
numberOfPassengers | Integer | Optional. Number of passengers transported by a user, on a trip. Some mileage allowances may include a premium on the amount reimbursed to the user, when there are some passengers. |
vehicleId | String | Mandatory. The identifier of the personal vehicle of the user, defined in his/her profile. |
waypoints | Waypoint[] | Optional. The waypoints describe the different points of the journey made by the user. |
total | BigDecimal | Optional. Amount of the expense, if not null will force the mileage total to this value instead of computing it with Jenji\u2019s system. |
actionUserId | String | Optional. Identifier of the user who updates the expense. This user must belong to the same organization as the one of the user who declared the expense. If not filled in, then the action maker becomes the user associated to the API token. |
type | ExpenseType | Mandatory. Type of the expense. |
UpdateAllowanceExpense
Updates an expense of type allowance. You may not change the underlying template after an expense has been created.
field | type | description |
---|---|---|
time | LocalDate | Mandatory. The day on which the expense occurred (yyyy-MM-dd). |
explanation | String | Optional. Any comment by the user, explaining in what context the expense occurred. |
billable | Boolean | Optional. Whether the expense may be billed to another party. |
tags | String[] | Optional. List of tags selected by the user, to associate to the expense. These tags may be used in graphical agents to search for expenses. |
customFields | Map<String,Object> | Optional. Map of custom field values, by custom field code. You must ensure that the type of the custom field value is consistent with the type of the custom field definition, recorded on the organization. |
taxes | Tax[] | Optional. Details of the taxes, when taxes apply only on parts of the total amount. |
attendees | String[] | Optional. List of identifiers of organization users who also participated in the event. The current user pays for all of them. |
country | String | Optional. Code of the country of the expense, a standard two-letter code in uppercase (e.g.: FR). May be filled only if the value is not set on the allowance template. |
label | String | Optional. The vendor of the service for which the expense has occurred (e.g. the name of a restaurant, a taxi company...). May be filled only if the value is not set on the allowance template. |
category | String | Optional. The category to which the expense belongs. May be filled only if the value is not set on the allowance template. |
paymentMethodId | String | Optional. The payment method used by the organization user to pay for the expense. It must be declared on the organization itself. May be filled only if the value is not set on the allowance template. |
actionUserId | String | Optional. Identifier of the user who updates the expense. This user must belong to the same organization as the one of the user who declared the expense. If not filled in, then the action maker becomes the user associated to the API token. |
type | ExpenseType | Mandatory. Type of the expense. |
Response body
The updated expense.
See Expense
List workflow actions
curl -X GET "https://api-test.jenji.io/api/org/v1/expenses/e02cbf8a-b0ea-4464-8823-3f981532648b/actions" \
-u API_USER_ID:SECRET_KEY \
{
"data" : [ "accept", "reject" ]
}
Request
GET /api/org/v1/expenses/{expenseId}/actions
Response body
List of possible actions for the specified expense. The action user must however have access to a profile authorized to perform the action, for the change of state to succeed.
field | type | description |
---|---|---|
data | String[] |
Execute workflow action
curl -X POST "https://api-test.jenji.io/api/org/v1/expenses/e02cbf8a-b0ea-4464-8823-3f981532648b/actions/accept" \
-u API_USER_ID:SECRET_KEY \
-H "Content-Type: application/json" \
--data '{
"actionUserId" : "manager-id"
}'
{
"id" : "e02cbf8a-b0ea-4464-8823-3f981532648b",
"userId" : "test@domain.com",
"organizationId" : "74dbaf20-7f22-45e6-8378-cf33cb775687",
"time" : "2020-12-20",
"total" : 7.11,
"currency" : "EUR",
"country" : "FR",
"billable" : false,
"state" : "ACCEPTED",
"label" : "Burrito",
"customFields" : {
"" : ""
},
"createdAt" : "2021-02-19T09:51:20.000000987Z",
"createdWith" : "api/v1",
"category" : "lunch",
"receiptKey" : "test@domain.com/634e8cfa-c4bb-480e-8190-6ecfd93ca7ff.jpg",
"paymentMethodId" : "8288ac38-8d04-484c-89ab-6bee22e8b602",
"totalWithoutTax" : 5.93,
"taxes" : [ {
"baseAmount" : 5.93,
"rate" : 20,
"amount" : 1.19
} ],
"type" : "STANDARD"
}
Change the state of an expense by triggering a workflow action.
You must specify an action code, which indicates the action to perform on the expense,
like "validate", "refuse" and so on.
Available action codes depend on the workflow configured for the organization, the expense state and the
profiles of the requesting user.
Request
POST /api/org/v1/expenses/{expenseId}/actions/{actionCode}
Path variables
parameter | type | required | description |
---|---|---|---|
actionCode | String | true |
Request body
The action execution request.
field | type | description |
---|---|---|
actionUserId | String | Optional. Identifier of the user who makes the action on the expense. This user must belong to the same organization as the one of the user who declared the expense. If not filled in, then the action maker becomes the user associated to the API token. |
comment | String | Any comment related to the change of state. |
Response body
The updated expense.
See Expense
Delete an expense
curl -X DELETE "https://api-test.jenji.io/api/org/v1/expenses/e02cbf8a-b0ea-4464-8823-3f981532648b" \
-u API_USER_ID:SECRET_KEY \
null
Delete an expense. This passes the expense into the DELETED state, resulting in it being excluded from all expense-related operating processes.
Request
DELETE /api/org/v1/expenses/{expenseId}
Get the url to upload a receipt
# openssl md5 -binary invoice.pdf | base64
# yaWmh42XtIzJZcHkGFnwNA==
curl -X POST "https://api-test.jenji.io/api/org/v1/receipts/upload-url" \
-u API_USER_ID:SECRET_KEY \
-H "Content-Type: application/json" \
--data '{
"fileType" : "pdf",
"userId" : "my-user-id",
"md5" : "yaWmh42XtIzJZcHkGFnwNA==",
"receiptType" : "EXPENSE"
}'
{
"uploadUrl" : "https://scanny-incoming-pdf.s3.eu-west-1.amazonaws.com/my-user-id/ab6178a0-c705-48ee-a16a-b4ad102b5797.pdf?X-Amz-Security-Token=FwoGZXIvYL%2BESkskIdq9SjfsyCLIAWVQmmZLEay7h7wO2jr4IQqk8oKQejhmgs5Vhm8DWPcd%2Bqv705M5KIgRKFj2ohJHjo7rZloOO6pap65mMFGGbxjSIlRvHewN82w46qhrf7vtgrruK3cZXiUpq5fMTS5VnDGFMaN%2FelTpMq7Gfi5C4%2FMjI51P840ufulxXgJ0mc%2BVm7O9E41J1nHm6s3uwqisySZnqY91CLKl5%2BiikCyz%2Behlk%2B4H%2Bk4UrwbeiZL4QigR4wDU0GsB4Y8f9PJE1uyxI3h9Xxua1fMkKKycuosGMi333qVyXqE71pwlPua%2FEvTIHDfzXfSfLMrz1e2I406btm4cS3vuL0Vs8ofHXAw%3D&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20211019T092833Z&X-Amz-SignedHeaders=content-md5%3Bhost&X-Amz-Expires=600&X-Amz-Credential=ASIAV5IPOSXFZ365H%2F20211019%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Signature=0ad5bc393b41e0540f1e9864c29f2b45b9923abc8c145d6043c94380a9cfcd",
"key" : "my-user-id/ab6178a0-c705-48ee-a16a-b4ad102b5797.pdf"
}
# Upload file via returned url
curl -X PUT --data-binary "@invoice.pdf" -H "Content-MD5: yaWmh42XtIzJZcHkGFnwNA==" https://scanny-incoming-pdf.s3.eu-west-1.amazonaws.com/my-user-id/ab6178a0-c705-48ee-a16a-b4ad102b5797.pdf?X-Amz-Security-Token=FwoGZXIvYL%2BESkskIdq9SjfsyCLIAWVQmmZLEay7h7wO2jr4IQqk8oKQejhmgs5Vhm8DWPcd%2Bqv705M5KIgRKFj2ohJHjo7rZloOO6pap65mMFGGbxjSIlRvHewN82w46qhrf7vtgrruK3cZXiUpq5fMTS5VnDGFMaN%2FelTpMq7Gfi5C4%2FMjI51P840ufulxXgJ0mc%2BVm7O9E41J1nHm6s3uwqisySZnqY91CLKl5%2BiikCyz%2Behlk%2B4H%2Bk4UrwbeiZL4QigR4wDU0GsB4Y8f9PJE1uyxI3h9Xxua1fMkKKycuosGMi333qVyXqE71pwlPua%2FEvTIHDfzXfSfLMrz1e2I406btm4cS3vuL0Vs8ofHXAw%3D&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20211019T092833Z&X-Amz-SignedHeaders=content-md5%3Bhost&X-Amz-Expires=600&X-Amz-Credential=ASIAV5IPOSXFZ365H%2F20211019%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Signature=0ad5bc393b41e0540f1e9864c29f2b45b9923abc8c145d6043c94380a9cfcd
Get the url to upload the receipt of an expense.
You need to compute the md5 of the file, then encode according to https://aws.amazon.com/premiumsupport/knowledge-center/data-integrity-s3/.
For java implementation:
byte[] receiptBytes = ... ;
byte[] md5Bytes = DigestUtils.md5(receiptBytes);
String md5hash = new String(Base64.encodeBase64(md5Bytes));
Later on, you will need to provide the MD5 hash as a header when calling the upload URL with your receipt:
curl -X PUT --data-binary @path_to_your_receipt -H "Content-MD5: UiDXFTZBDEg0eA6vVUm1Zg==" {the_upload_url}
Request
POST /api/org/v1/receipts/upload-url
Request body
Get the url to upload the receipt of an expense into Jenji Storage.
field | type | description |
---|---|---|
fileType | String | Mandatory. The file extension, one of "jpg", "jpeg", "pdf". |
userId | String | Mandatory. The identifier of the user emitting the expense, awaiting reimbursement. |
md5 | String | Mandatory. Encoded MD5 hash of your receipt |
receiptType | ReceiptType | Optional. Receipt type: EXPENSE (default) or EXPENSE_REQUEST |
Response body
A secure URL to where a receipt may be uploaded, as well as a technical key pointing to the location, to be referenced into the expense. This URL remains valid for a few minutes only.
See ReceiptUpload
ReceiptType
value | description |
---|---|
EXPENSE | |
EXPENSE_REQUEST |
Get the url to download the receipt of an expense
curl -X POST "https://api-test.jenji.io/api/org/v1/expenses/e02cbf8a-b0ea-4464-8823-3f981532648b/receipts/download-url" \
-u API_USER_ID:SECRET_KEY \
{
"downloadUrl" : "https://scanny.s3.eu-west-1.amazonaws.com/victor.clogenson%2Be1r20%40jenji.io/c749ff23-122f-4a17-81fd-97de17690d41.jpg?X-Amz-Security-Token=FwoGZXIvYXdzECsaDHhkrZ9CiSl38zJyETWhwsB9Igs3yg04EhM%3D&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20211119T093608Z&X-Amz-SignedHeaders=host&X-Amz-Expires=599&X-Amz-Credential=ASIAV5IU6VPOTBN3QU2D%2F20211119%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Signature=e4a946de0af7ac04dfce77dd438"
}
Get the url to download the receipt of an expense.
Request
POST /api/org/v1/expenses/{expenseId}/receipts/download-url
Response body
A secure URL from which the receipt of an expense may be downloaded. This URL remains valid for a few minutes only.
See ReceiptDownload
Get expense warnings
curl -X GET "https://api-test.jenji.io/api/org/v1/expenses/e32d1d51-fa3e-497b-aa39-91b1ef8b48cc/warnings" \
-u API_USER_ID:SECRET_KEY \
{
"data" : [ {
"warningRuleId" : "db8b379c-1cd9-4d58-a986-2db82eec5700",
"userId" : "ceb316c0-1ef3-48b3-b74e-6204ecd9cf92",
"time" : "2020-12-24",
"updatedAt" : "2023-03-30T07:50:57.434440Z",
"code" : "m30"
} ]
}
Return all warnings of an expense
Request
GET /api/org/v1/expenses/{expenseId}/warnings
Response body
field | type | description |
---|---|---|
data | ExpenseWarning[] | |
data[].warningRuleId | String | The identifier of the warning rule. Either the identifier of a custom rule (a UUID), or a reserved rule identifier (e.g. "duplicate"). |
data[].userId | String | Identifier of the user who own the warning (user of the targeted expense) |
data[].time | LocalDate | Day on which the expense owning the warning occurred. |
data[].updatedAt | OffsetDateTime | Timestamp of the update of the warning. |
data[].code | String | The custom code chosen when creating the warning rule. |
data[].labelsPerLanguage | Map<String,String> | Custom labels for the warning, by language code. Custom labels are optional, they are only set for warnings generated by certain warning rules. When missing, default labelling algorithms should be applied, e.g. derive appropriate labels from the warning code, or from the default labels of the associated warning rule. |
data[].isPreventingValidation | Boolean | Indicates whether this warning should prevent the validation of the expense/request or not |
data[].mutedAt | OffsetDateTime | Timestamp of the muting of the warning. |
data[].mutedBy | String | Identifier of the user who has muted the warning. |
data[].linkedExpensesIds | String[] | Identifiers of the expenses that are related to the warning. |
Add a warning to an Expense
curl -X PUT "https://api-test.jenji.io/api/org/v1/expenses/e32d1d51-fa3e-497b-aa39-91b1ef8b48cc/warnings/db8b379c-1cd9-4d58-a986-2db82eec5700" \
-u API_USER_ID:SECRET_KEY \
-H "Content-Type: application/json" \
--data '{
"code" : "m30"
}'
{
"warningRuleId" : "db8b379c-1cd9-4d58-a986-2db82eec5700",
"userId" : "ceb316c0-1ef3-48b3-b74e-6204ecd9cf92",
"time" : "2020-12-24",
"updatedAt" : "2023-03-30T07:50:57.436438Z",
"code" : "m30"
}
Add a warning to an expense. Rule must exist.
The warning rule ID path parameter can only refer to a warning rule that was previously created by API (= type EXTERNAL). Internal Jenji warning rule ID cannot be used here !
You can either provide the Jenji ID, that was returned by the Warning rule creation API, or the external rule ID if you provided one on Warning rule creation API call. To provide an external rule ID, use the format 'ext-your-warning-rule-id'.
Request
PUT /api/org/v1/expenses/{expenseId}/warnings/{warningRuleId}
Path variables
parameter | type | required | description |
---|---|---|---|
warningRuleId | String | true | can be either Jenji ID or an external ID using the format 'ext-your-warning-rule-id' |
Request body
field | type | description |
---|---|---|
code | String | For rules with multiple options, the code is required and must be one of the rule code |
Response body
An expense warning describes a custom rule to be applied to an expense, to check some of its state. For instance, a "duplicate" warning tells when 2 expenses of the same amount are created on the same day.
See ExpenseWarning
Remove a warning from an expense
curl -X DELETE "https://api-test.jenji.io/api/org/v1/expenses/e32d1d51-fa3e-497b-aa39-91b1ef8b48cc/warnings/db8b379c-1cd9-4d58-a986-2db82eec5700" \
-u API_USER_ID:SECRET_KEY \
null
Delete a warning from an expense. Rule must exist.
The warning rule ID path parameter can only refer to a warning rule that was previously created by API (= type EXTERNAL). Internal Jenji warning rule ID cannot be used here !
You can either provide the Jenji ID, that was returned by the Warning rule creation API, or the external rule ID if you provided one on Warning rule creation API call. To provide an external rule ID, use the format 'ext-your-warning-rule-id'.
Request
DELETE /api/org/v1/expenses/{expenseId}/warnings/{warningRuleId}
Path variables
parameter | type | required | description |
---|---|---|---|
warningRuleId | String | true | can be either Jenji ID or an external ID using the format 'ext-your-warning-rule-id' |
Get export ids
curl -X GET "https://api-test.jenji.io/api/org/v1/expenses/682fd445-c433-4ada-86b5-4bcdc9d0eb6a/exports" \
-u API_USER_ID:SECRET_KEY \
{
"expenseId" : "682fd445-c433-4ada-86b5-4bcdc9d0eb6a",
"accounting" : "142382f3-3e48-4dd6-a564-4283075b31b1",
"payroll" : "228a0a45-58df-4112-9254-af1067939e6c"
}
Return the accounting an payroll export identifiers containing the expenses
Request
GET /api/org/v1/expenses/{expenseId}/exports
Response body
Contains ids of exports containing expense
field | type | description |
---|---|---|
expenseId | String | Expense identified |
accounting | String | Accounting export identifier |
payroll | String | Payroll export identifier |
Delete accounting export
curl -X DELETE "https://api-test.jenji.io/api/org/v1/expenses/682fd445-c433-4ada-86b5-4bcdc9d0eb6a/exports/accounting" \
-u API_USER_ID:SECRET_KEY \
null
curl -X DELETE "https://api-test.jenji.io/api/org/v1/expenses/682fd445-c433-4ada-86b5-4bcdc9d0eb6a/exports/payroll" \
-u API_USER_ID:SECRET_KEY \
null
Delete the specified export information of the expense
Request
DELETE /api/org/v1/expenses/{expenseId}/exports/{exportType}
Path variables
parameter | type | required | description |
---|---|---|---|
exportType | String | true | accounting or payroll |
Expense Requests
Set of methods to search expense requests. These methods may only be called by the organization for its own expense requests, or by its bookkeeper.
Search expense requests of your organization
Search for expense requests of your own organization (as a root admin), according to specified criteria.
Request
POST /api/org/v1/expense-requests/search
Request body
The criteria to search for.
field | type | description |
---|---|---|
start | LocalDate | Mandatory. Inclusive start of the search interval as a local date (YYYY-MM-DD). |
end | LocalDate | Mandatory. Inclusive end of the search interval as a local date (YYYY-MM-DD). |
states | String[] | Optional. List of states to match when searching expenses. Theses states are configured in workflow states, contact support for possibles values. |
Response body
List of expense requests matching the search criteria.
field | type | description |
---|---|---|
data | ExpenseRequest[] | |
data[].id | String | Unique identifier of the expense request in Jenji (a UUID). |
data[].shortId | String | Unique short Id identifier |
data[].label | String | Label of expense request |
data[].type | String | Type of expense request |
data[].userId | String | Unique identifier of the organization user for which the expense request applies (either an email or a UUID, depending on the acquisition channel). |
data[].state | String | State of the expense request |
data[].comment | String | Explanation for the expense expense request, provided by the user who has created the expense. This explanation will be read by the manager who approves the expense. |
data[].expenses | String[] | Expenses Id of linked expenses. |
data[].creationDate | OffsetDateTime | Creation date of expense Request. |
data[].customFields | Map<String,Object> | Custom fields are defined by organizations, to help classify an expense request for analytic purposes. This fields maps values for all required custom fields. |
data[].files | ExpenseRequestFile[] | Expense request attached files. |
Create expense request
Create a new expense request.
Request
POST /api/org/v1/expense-requests
Request body
Expense request data.
field | type | description |
---|---|---|
label | String | Mandatory. Label of expense request |
type | String | Mandatory. Type of expense request. Accepted values depends of your organization configuration |
userId | String | Mandatory. Unique identifier of the organization user for which the expense request applies (either an email or a UUID, depending on the acquisition channel). |
comment | String | Optional. Explanation for the expense expense request, provided by the user who has created the expense. This explanation will be read by the manager who approves the expense. |
files | NamedFile[] | Optional. Request files. |
files[].name | String | Real file name (displayed in UX). |
files[].file | String | File reference in Jenji storage system. |
customFields | Map<String,Object> | Optional. Map of custom field values, by custom field code. You must ensure that the type of the custom field value is consistent with the type of the custom field definition, recorded on the organization. |
Response body
Created expense request.
See ExpenseRequest
Get expense request
Get an expense request.
Request
GET /api/org/v1/expense-requests/{requestId}
Response body
Expense request.
See ExpenseRequest
Update expense request
Update an expense request. All data will be overwrite by input. If you need to make a partial update, use the patch request.
Request
PUT /api/org/v1/expense-requests/{requestId}
Path variables
parameter | type | required | description |
---|---|---|---|
requestId | String | true | Expense request id. |
Request body
field | type | description |
---|---|---|
label | String | Mandatory. Label of expense request |
comment | String | Optional. Explanation for the expense expense request, provided by the user who has created the expense. This explanation will be read by the manager who approves the expense. |
files | NamedFile[] | Optional. Request files. |
files[].name | String | Real file name (displayed in UX). |
files[].file | String | File reference in Jenji storage system. |
customFields | Map<String,Object> | Optional. Map of custom field values, by custom field code. You must ensure that the type of the custom field value is consistent with the type of the custom field definition, recorded on the organization. |
Response body
Updated expense request.
See ExpenseRequest
Patch expense request
Patch an expense request. Only non null value sent will be used.
Files in body will be added to the request, renamed id the same file
, and no files will be removed.
Request
PATCH /api/org/v1/expense-requests/{requestId}
Path variables
parameter | type | required | description |
---|---|---|---|
requestId | String | true | Expense request id. |
Request body
field | type | description |
---|---|---|
label | String | Mandatory. Label of expense request |
comment | String | Optional. Explanation for the expense expense request, provided by the user who has created the expense. This explanation will be read by the manager who approves the expense. |
files | NamedFile[] | Optional. Request files. |
files[].name | String | Real file name (displayed in UX). |
files[].file | String | File reference in Jenji storage system. |
customFields | Map<String,Object> | Optional. Map of custom field values, by custom field code. You must ensure that the type of the custom field value is consistent with the type of the custom field definition, recorded on the organization. |
Response body
Updated expense request.
See ExpenseRequest
List workflow actions
Request
GET /api/org/v1/expense-requests/{requestId}/actions
Response body
List of possible actions for the specified request.
field | type | description |
---|---|---|
data | String[] |
Execute workflow action
Change the state of an request by triggering a workflow action.
You must specify an action code, which indicates the action to perform on the request.
Available action codes depend on the workflow configured for the organization, the request state.
Request
POST /api/org/v1/expense-requests/{requestId}/actions/{actionCode}
Path variables
parameter | type | required | description |
---|---|---|---|
actionCode | String | true |
Request body
The action execution request.
field | type | description |
---|---|---|
actionUserId | String | Optional. Identifier of the user who makes the action on the request. This user must belong to the same organization as the one of the user who declared the request. If not filled in, then the action maker becomes the user associated to the API token. |
comment | String | Any comment related to the change of state. |
Response body
The updated expense.
See ExpenseRequest
Exports
Set of apis to generate and download exports files
Compute export download url
curl -X POST "https://api-test.jenji.io/api/tools/v1/tools/exports/download-url" \
-u API_USER_ID:SECRET_KEY \
-H "Content-Type: application/json" \
--data '{
"id" : "afc88dc2-8aed-47ce-a58a-5e000a8263d1",
"type" : "USER"
}'
{
"id" : "afc88dc2-8aed-47ce-a58a-5e000a8263d1",
"generationStatus" : "GENERATED",
"downloadUrl" : "https://export-user-jenji-io-ctrwmoknieuwnyhzkxk71t8hk9frkeuw1a-s3alias.s3.eu-west-1.amazonaws.com/157856-051d-465a-9135-024a05531435/lUjWB-H_btraxOvy0izbsg/jenji-export_2022-05-10_14-26.csv??X-Amz-Security-Token=FwoGZXIvYL%2BESkskIdq9SjfsyCLIAWVQmmZLEay7h7wO2jr4IQqk8oKQejhmgs5Vhm8DWPcd%2Bqv705M5KIgRKFj2ohJHjo7rZloOO6pap65mMFGGbxjSIlRvHewN82w46qhrf7vtgrruK3cuosGMi333qVyXqE71pwlPua%2FEvTIHDfzXfSfLMrz1e2I406btm4cS3vuL0Vs8ofHXAw%3D&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20211019T092833Z&X-Amz-SignedHeaders=content-md5%3Bhost&X-Amz-Expires=600&X-Amz-Credential=ASIAV5IPOSXFZ365H%2F20211019%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Signature=0ad5bc393b41e0540f1e9864c29f2b45b9923abc8c145d6043c94380a9cfcd"
}
curl -X POST "https://api-test.jenji.io/api/tools/v1/tools/exports/download-url" \
-u API_USER_ID:SECRET_KEY \
-H "Content-Type: application/json" \
--data '{
"id" : "022570df-99bd-4b0e-9151-54ad32b0187a",
"type" : "ACCOUNTING"
}'
{
"id" : "022570df-99bd-4b0e-9151-54ad32b0187a",
"generationStatus" : "IN_PROGRESS"
}
curl -X POST "https://api-test.jenji.io/api/tools/v1/tools/exports/download-url" \
-u API_USER_ID:SECRET_KEY \
-H "Content-Type: application/json" \
--data '{
"id" : "d35264c5-33ea-4305-8367-94f4fa451cd9",
"type" : "GROUP"
}'
{
"id" : "d35264c5-33ea-4305-8367-94f4fa451cd9",
"generationStatus" : "ERROR"
}
Compute an url to download an export file. This url will be a secured url that is valid only 5 minutes. After this time, trying to use it will return an error.
Request
POST /api/tools/v1/tools/exports/download-url
Request body
The details of the export to download
field | type | description |
---|---|---|
id | String | Export id |
type | ExportType | Type of export |
Response body
The url if available
field | type | description |
---|---|---|
id | String | Export id |
generationStatus | ExportGenerationStatus | Status of the export file generation |
downloadUrl | String | Download secured url for the export file, can be empty if status is different from GENERATED. Doing an HTTP GET request on this url will download the file. This url is only valid for 5 minutes. |
ExportType
In jenji there is multiple type of exports that have different visibility and use-cases
value | description |
---|---|
ACCOUNTING | Accounting export |
PAYROLL | Payroll export |
USER | Export generated and only visible by a user |
GROUP | Shared export |
ExportGenerationStatus
value | description |
---|---|
IN_PROGRESS | Export generation is still in progress, download url will be available later |
ERROR | Export failed to be generated, there is no output file and no url |
GENERATED | Export has been correctly generated and can be downloaded |
Bookkeepers
Set of methods to create, update or view bookkeepers. These methods may only be used by a master bookkeeper, or by the bookkeeper of which it is question.
List all bookkeepers
A master bookkeeper retrieves the list of all bookkeepers which he/she is allowed to manage.
Request
GET /api/bk/v1/bookkeepers
Response body
List of the bookkeepers managed by the master bookkeeper.
field | type | description |
---|---|---|
data | Bookkeeper[] | |
data[].id | String | Unique identifier of the bookkeeper in Jenji (a UUID). |
data[].name | String | The name of the company. |
data[].jenjiOrganizationId | String | The bookkeeper may also use Jenji as a service for the management of its own expenses. If so, this field contains the identifier of its Jenji organization. |
data[].masterBookkeeperId | String | This field contains the identifier of the master bookkeeper which manages the bookkeeper, if there is one. The master bookkeeper may perform most operations in the name of its managed bookkeeper. |
data[].clientOptions | BookkeeperClientOptions | Newly-added clients are declared with default options, which are reported below. To date, these options may not be changed by API, but only through our Support. |
data[].groups | BookkeeperGroup[] | The hierarchy of groups of the bookkeeper (each group represents an operational team of the bookkeeper). The top group is named "root group", it is the default group and it may not be deleted. |
data[].createdAt | OffsetDateTime | Timestamp of creation of the bookkeeper. |
data[].updatedAt | OffsetDateTime | Timestamp of last update of the bookkeeper. This timestamp is updated if any header data, or data of the root group, are modified. It is not updated if a subgroup has changed. |
View a bookkeeper
curl -X GET "https://api-test.jenji.io/api/bk/v1/bookkeepers/367a75ae-3fa0-4a7a-9e19-5b059f1568c3" \
-u API_USER_ID:SECRET_KEY \
{
"id" : "367a75ae-3fa0-4a7a-9e19-5b059f1568c3",
"name" : "Bookkeeper name",
"clientOptions" : {
"clientsBilledByJenji" : false,
"manageClientVault" : false,
"enableClientVaultOnNewClient" : true,
"allowSoloPlanClient" : false,
"mustUseTemplate" : true
},
"groups" : [ {
"id" : "root",
"name" : "Bookkeeper name",
"createdAt" : "2021-02-19T09:51:20.000000987Z",
"updatedAt" : "2021-07-03T15:11:56.000000306Z"
}, {
"id" : "0932cc53-3b8b-49aa-9153-a16906637276",
"name" : "Sub-group 1",
"parentGroupId" : "root",
"createdAt" : "2021-02-19T09:51:20.000000987Z",
"updatedAt" : "2021-07-03T15:11:56.000000306Z"
} ],
"createdAt" : "2021-02-19T09:51:20.000000987Z",
"updatedAt" : "2021-07-03T15:11:56.000000306Z"
}
Retrieve detailed data of a bookkeeper.
Request
GET /api/bk/v1/bookkeepers/{bookkeeperId}
Response body
Detailed information of a bookkeeper.
See Bookkeeper
Create a new bookkeeper
A master bookkeeper creates a new bookkeeper, and gains access to it. The data used to create that bookkeeper are partly provided by the caller, and partly retrieved from a template specified by the caller.
Request
POST /api/bk/v1/bookkeepers
Request body
Contains the custom bookkeeper data, as well as the template to use.
field | type | description |
---|---|---|
name | String | Mandatory.The company name of the bookkeeper to be created. |
templateId | String | Mandatory. The identifier of a bookkeeper template (a UUID), used to populate the default values of the bookkeeper. You must use one of the template identifiers which was provided to you by our Ops. |
Response body
The newly-created bookkeeper, with a unique ID.
See Bookkeeper
Update an existing bookkeeper
Modified header data of a bookkeeper. The data originally filled from a template may not be modified, only the custom data may be changed.
Request
PUT /api/bk/v1/bookkeepers/{bookkeeperId}
Request body
The custom data to update.
field | type | description |
---|---|---|
name | String | Mandatory. The name of the bookkeeper group, e.g. the designation of the team. |
Response body
The bookkeeper, with updated data.
See Bookkeeper
Create a new group
Add a new group to a bookkeeper. The caller may specify a parent group to form a hierarchy, or leave the parent null, in which case the group will be created as a direct child of the root group.
Request
POST /api/bk/v1/bookkeepers/{bookkeeperId}/groups
Request body
Data used to create the new group.
field | type | description |
---|---|---|
name | String | Mandatory. The name of the bookkeeper group, e.g. the designation of the team. |
parentGroupId | String | Optional. The parent group of the group to be created. If left empty, then the group parent is automatically set to the bookkeeper root group. |
Response body
The newly-created group. To see the entire hierarchy, make a GET on the bookkeeper itself.
See BookkeeperGroup
List all clients
Retrieve the list of clients of a specific bookkeeper.
Request
GET /api/bk/v1/bookkeepers/{bookkeeperId}/clients
Response body
List of the organizations managed by the bookkeeper.
field | type | description |
---|---|---|
data | BookkeeperClient[] | |
data[].bookkeeperId | String | The identifier of bookkeeper party. |
data[].organizationId | String | The identifier of organization managed by the bookkeeper. |
data[].internalId | String | Optional field, an internal id for the contract in the bookkeeper information system. |
data[].explanation | String | Optional field, any form of comment from the bookkeeper to clarify the nature of the contract, or any worthwhile information to pay attention to. |
Create a new client
A new organization is created and referenced as client for a bookkeeper. The data used to create that organization are partly provided by the caller, and partly retrieved from a template specified by the caller.
Request
POST /api/bk/v1/bookkeepers/{bookkeeperId}/clients
Request body
Contains the custom organization data, as well as the template to use.
field | type | description |
---|---|---|
name | String | Mandatory. The company name of the organization to be created. |
internalId | String | Optional. The identifier of the organization, as declared in the information system of the bookkeeper. |
explanation | String | Optional. Any informative comment by the bookkeeper about this client. May be be retrieved and displayed to bookkeeper users. |
templateId | String | Mandatory. The identifier of an organization template (a UUID), used to populate the default values of the organization. You must use one of the template identifiers which was provided to you by our Ops. |
Response body
The newly-created organization, attached to the bookkeeper, with a unique ID.
See BookkeeperClient
Add states to a client
Add states to an client.
Request
PUT /api/bk/v1/bookkeepers/{bookkeeperId}/clients/{clientId}/states
Request body
Data representing states to add to the client.
field | type | description |
---|---|---|
states | String[] | List of states you wish to add or remove from a client. From:
|
Response body
The updated organization.
field | type | description |
---|
Remove states from an client
Remove states from a client.
Request
DELETE /api/bk/v1/bookkeepers/{bookkeeperId}/clients/{clientId}/states
Request body
Data representing the states to remove from the client.
field | type | description |
---|---|---|
states | String[] | List of states you wish to add or remove from a client. From:
|
Response body
The updated organization.
field | type | description |
---|
Apply template to a client
Apply the configuration of a new template on an organization.
All expenses will be hard reset, only the following attributes will be kept:
- billable
- country
- created
- explanation
- ID
- receipt
- route
- seller
- taxes
- time
- total
- total wo tax
- user ID
- vaulted at
Custom profiles will be overridden.
Expense workflows will be overridden.
Expense request workflows will be overridden.
Accounting configurations will be kept.
Warning rules will be kept.
The configuration of the template will be applied to the target client organization.
The following organization's attributes will be overridden, if present in the template configuration:
- available languages
- access template ID
- login suffix
- logo
- countries
- currencies
- categories threshold
- custom group exports
- custom fields
- feature flags
- group custom fields
- user custom fields
- expense request custom fields
- external cloud config
- fixed mileage rate
- payment methods
- additional categories
- plan
It also allows to update the accounting configuration.
Changing the accounting template will change accounting export format, columns, ... However, specific organization configuration like account number mappings will not be updated.
Request
POST /api/bk/v1/bookkeepers/{bookkeeperId}/clients/{clientId}/apply-template
Request body
Data representing the template to apply to the client, at least one attribute is required.
field | type | description |
---|---|---|
templateId | String | Identifier of the template to apply. Format: UUID v4. If null, no modification will be done on organization. |
accountingTemplateId | String | Identifier of the accounting template to apply. Format: UUID v4. If null, no modification will be done on accounting configuration. |
Response body
Details of the updated organization.
See Organization
Find users by login
curl -X GET "https://api-test.jenji.io/api/bk/v1/bookkeepers/97643509-abb0-4a46-8964-69ab9a9257db/clients/users/john.doe@sample.com" \
-u API_USER_ID:SECRET_KEY \
{
"user" : {
"id" : "01a3d5c6-1b25-4947-93fe-782e588b84bd",
"login" : "john.doe@sample.com",
"firstName" : "John",
"lastName" : "Doe"
},
"organization" : {
"id" : "e87c35cb-12d8-4fca-8ea6-be75e36c4822",
"name" : "Demo organization"
}
}
Get a list of specific user and their organization if users exist.
Request
GET /api/bk/v1/bookkeepers/{bookkeeperId}/clients/users/{login}
Path variables
parameter | type | required | description |
---|---|---|---|
login | String | true | The login of users. |
Response body
List of existing users for this login with their organizations.
field | type | description |
---|
List all users
curl -X GET "https://api-test.jenji.io/api/bk/v1/bookkeepers/fdbc7680-02b9-4361-92d3-02e822f506a8/users" \
-u API_USER_ID:SECRET_KEY \
[ {
"id" : "56bcf656-5f13-44a8-9cfb-36b90f897b0f",
"bookkeeperId" : "fdbc7680-02b9-4361-92d3-02e822f506a8",
"groupId" : "root",
"firstName" : "Jeanne",
"lastName" : "Dupont",
"updatedAt" : "2021-02-19T09:58:31.000000666Z",
"createdAt" : "2021-02-19T09:52:20.000000777Z"
}, {
"id" : "b2f3d208-ea3b-4270-b8f1-b33cc20c04b9",
"bookkeeperId" : "fdbc7680-02b9-4361-92d3-02e822f506a8",
"groupId" : "6fdfea20-4c78-4d23-93df-8c69fa9f0696",
"firstName" : "Valentine",
"lastName" : "Dubois",
"updatedAt" : "2021-02-19T09:58:31.000000666Z",
"createdAt" : "2021-02-19T09:52:20.000000777Z"
} ]
List all bookkeeper users of a specific bookkeeper.
Request
GET /api/bk/v1/bookkeepers/{bookkeeperId}/users
Response body
List of bookkeeper users for the bookkeeper.
field | type | description |
---|---|---|
data | BookkeeperUser[] | |
data[].id | String | Unique identifier of the User in Jenji (UUID or email, depending on the original registration channel). |
data[].bookkeeperId | String | Unique identifier of the bookkeeper to which the user belongs. |
data[].groupId | String | Unique identifier of the group of the bookkeeper to which the user belongs. |
data[].internalId | String | Optional field, containing the internal identifier of the user in the information system of the bookkeeper. This may help when querying the APIs and performing various mapping tasks. |
data[].firstName | String | First name of the user, like "Alex" in "Alex Pence". |
data[].lastName | String | Last name of the user, like "Pence" in "Alex Pence". |
data[].updatedAt | OffsetDateTime | Timestamp of the last update of the user. |
data[].createdAt | OffsetDateTime | Timestamp of the creation of the user. |
data[].blockedAt | OffsetDateTime | Timestamp of the blocking of the user. This field is null when the user is not blocked. |
Create a new user
Create a new bookkeeper user and adds it to a specific group of the bookkeeper.
Request
POST /api/bk/v1/bookkeepers/{bookkeeperId}/users
Request body
The data required to create the user.
field | type | description |
---|---|---|
firstName | String | Optional. First name of the user, like "Alex" in "Alex Pence". |
lastName | String | Optional. Last name of the user, like "Pence" in "Alex Pence". |
groupId | String | Optional. Identifier of the bookkeeper group to which the user must be added. If left empty, then the user will be attached to the root group of the bookkeeper. |
internalId | String | Optional. Identifier of the user in the information system of the bookkeeper. |
Response body
The newly-created user, with a unique ID.
See BookkeeperUser
Update template categories
Update the list of categories for a template.
If the template belongs to the bookkeeper, it will be updated directly with the new categories.
If instead the template belongs to the master bookkeeper, the template will be untouched and the categories will
override that of the template only in the context of this bookkeeper.
New organizations created from this template after this change will use the updated list of categories.
Existing organizations will be updated asynchronously inside a 24h window. Multiple successive updates to a
same template will effectively be squashed as a unique update for existing organizations. Existing categories
that are not present in the new template will NOT be deleted but will be disabled instead to preserve global data
consistency (such as expenses referencing those categories).
Request
POST /api/bk/v1/bookkeepers/{bookkeeperId}/templates/{templateId}/categories
Path variables
parameter | type | required | description |
---|---|---|---|
templateId | String | true | Id of an existing template. |
Request body
The desired complete list of categories for this template.
See Category
Response body
The actual list of categories computed for the template. This list can differ for the input list in case default categories have been omitted. In such a scenario, default categories are set as disabled.
field | type | description |
---|
Create a new template from existing template
A new organization template is created and referenced for a bookkeeper. The resulting template will be the copy of the provided templateId.
Request
POST /api/bk/v1/bookkeepers/{bookkeeperId}/templates
Request body
Contains the custom organization data, as well as the template to use.
field | type | description |
---|---|---|
name | String | Mandatory. The company name of the organization to be created. |
internalId | String | Optional. The identifier of the template, as declared in the information system of the bookkeeper. |
explanation | String | Optional. Any informative comment by the bookkeeper about this client. May be be retrieved and displayed to bookkeeper users. |
templateId | String | Mandatory. The identifier of an organization template (a UUID), used to populate the default values of the organization. You must use one of the template identifiers which was provided to you by our Ops. |
Response body
The newly-created organization, attached to the bookkeeper, with a unique ID.
Update vault configuration
# Enable a 20Go vault on organization
curl -X PUT "https://api-test.jenji.io/api/org/v1/bookkeepers/5f9e71fb-0186-4536-8ae0-79f54ca61713/organizations/5046b09c-3d51-4c6b-a4e2-7d9760450eb6/vault" \
-u API_USER_ID:SECRET_KEY \
-H "Content-Type: application/json" \
--data '{
"enabled" : true,
"capacity" : 20
}'
{
"maxCapacity" : 20,
"consumedCapacity" : 0
}
# Disable vault on organization
curl -X PUT "https://api-test.jenji.io/api/org/v1/bookkeepers/5f9e71fb-0186-4536-8ae0-79f54ca61713/organizations/5046b09c-3d51-4c6b-a4e2-7d9760450eb6/vault" \
-u API_USER_ID:SECRET_KEY \
-H "Content-Type: application/json" \
--data '{
"enabled" : false
}'
{
"message" : "Vault disabled"
}
Request
PUT /api/org/v1/bookkeepers/{bookkeeperId}/organizations/{organizationId}/vault
Path variables
parameter | type | required | description |
---|---|---|---|
organizationId | String | true |
Request body
field | type | description |
---|---|---|
enabled | Boolean | Mandatory. Whether the vault should be enabled or not. |
capacity | Long | The desired vault capacity, in Mb |
Response body
field | type | description |
---|---|---|
maxCapacity | BigDecimal | The maximum capacity, in Mb |
consumedCapacity | BigDecimal | The consumed capacity, in Mb. Note that it is only recomputed several times a day. |
message | String | Explanation message, if necessary |
Get consumed/max vault capacities
curl -X GET "https://api-test.jenji.io/api/org/v1/bookkeepers/5f9e71fb-0186-4536-8ae0-79f54ca61713/organizations/5046b09c-3d51-4c6b-a4e2-7d9760450eb6/vault" \
-u API_USER_ID:SECRET_KEY \
{
"maxCapacity" : 20,
"consumedCapacity" : 11.42
}
Request
GET /api/org/v1/bookkeepers/{bookkeeperId}/organizations/{organizationId}/vault
Path variables
parameter | type | required | description |
---|---|---|---|
organizationId | String | true |
Response body
field | type | description |
---|---|---|
maxCapacity | BigDecimal | The maximum capacity, in Mb |
consumedCapacity | BigDecimal | The consumed capacity, in Mb. Note that it is only recomputed several times a day. |
message | String | Explanation message, if necessary |
User Absences
Get absences for a user for a period
curl -X GET "https://api-test.jenji.io/api/org/v1/organizations/{organizationId}/users/ed897198-a448-4b92-9fea-5924427c5446/absences" \
-u API_USER_ID:SECRET_KEY \
[ {
"userId" : "ed897198-a448-4b92-9fea-5924427c5446",
"date" : "2018-01-01"
} ]
Get absences for a user for a period. It returns a list of absences for each day with an absence on the period. Start date has to be before end date, else a {@link BadRequestException} is thrown.
Request
GET /api/org/v1/organizations/{organizationId}/users/{userId}/absences
Path variables
parameter | type | required | description |
---|---|---|---|
userId | String | true | Identifier of the user. |
Query parameters
parameter | type | required | description |
---|---|---|---|
from | String | true | Start date of the period. Format: yyyy-MM-dd, inclusive. |
to | String | true | End date of the period. Format: yyyy-MM-dd, inclusive. |
Response body
List of absences for the user for the period.
field | type | description |
---|
Get a absence for a user
curl -X GET "https://api-test.jenji.io/api/org/v1/organizations/{organizationId}/users/ed897198-a448-4b92-9fea-5924427c5446/absences/date/2018-01-01" \
-u API_USER_ID:SECRET_KEY \
{
"userId" : "ed897198-a448-4b92-9fea-5924427c5446",
"date" : "2018-01-01"
}
Get an absence for a user. If the date is not a valid date, a {@link BadRequestException} is thrown.
Request
GET /api/org/v1/organizations/{organizationId}/users/{userId}/absences/date/{date}
Path variables
parameter | type | required | description |
---|---|---|---|
userId | String | true | Identifier of the user. |
date | String | true | Date of the absence. Format: yyyy-MM-dd |
Response body
Output DTO for a user absence.
field | type | description |
---|---|---|
userId | String | Unique identifier of the User in Jenji (UUID or email, depending on the acquisition channel). |
date | LocalDate | Date of the absence. Format: YYYY-MM-DD. |
Create absences for a user for a period
curl -X POST "https://api-test.jenji.io/api/org/v1/organizations/{organizationId}/users/ed897198-a448-4b92-9fea-5924427c5446/absences" \
-u API_USER_ID:SECRET_KEY \
-H "Content-Type: application/json" \
--data '{
"from" : "2018-01-01",
"to" : "2018-01-02"
}'
[ {
"userId" : "ed897198-a448-4b92-9fea-5924427c5446",
"date" : "2018-01-01"
}, {
"userId" : "ed897198-a448-4b92-9fea-5924427c5446",
"date" : "2018-01-02"
} ]
Create absences for a user for a period. It creates an absence for each day of the period. If an absence already exists for a day, it will return a 409 conflict, and no absence will be created. Start date has to be before end date, else a {@link BadRequestException} is thrown.
Request
POST /api/org/v1/organizations/{organizationId}/users/{userId}/absences
Path variables
parameter | type | required | description |
---|---|---|---|
userId | String | true | Identifier of the user. |
Request body
Period of absences to create. dates are in format yyyy-MM-dd.
field | type | description |
---|---|---|
from | LocalDate | Start date of the absence period. Format: yyyy-MM-dd. Inclusive. |
to | LocalDate | End date of the absence period. Format: yyyy-MM-dd. Inclusive. |
Response body
List of absences created.
field | type | description |
---|
Delete absence for a user for a date
curl -X DELETE "https://api-test.jenji.io/api/org/v1/organizations/{organizationId}/users/ed897198-a448-4b92-9fea-5924427c5446/absences/date/2018-01-01" \
-u API_USER_ID:SECRET_KEY \
null
Delete absence for a user for a date. If an absence does not exist for the date, it will return a 404 not found.
Request
DELETE /api/org/v1/organizations/{organizationId}/users/{userId}/absences/date/{date}
Path variables
parameter | type | required | description |
---|---|---|---|
userId | String | true | Identifier of the user. |
date | String | true | Date of the absence to delete. Format is yyyy-MM-dd. |
Misc
Set of utility methods to perform cross-domain mileage computations. May only be used by an organization.
Compute addresses point
Geocode addresses and get geo positions.
Request
POST /api/tools/v1/tools/mileage/address
Request body
The coordinates of the waypoints.
field | type | description |
---|---|---|
startAddress | String | Optional. Start address of the trip. If missing, then start longitude and latitude must be filled. |
startLongitude | BigDecimal | Optional. Start longitude of the trip ([-180.0; +180.0]). |
startLatitude | BigDecimal | Optional. Start latitude of the trip ([-90.0; +90.0]). |
endAddress | String | Optional. End address of the trip. If missing, then end longitude and latitude must be filled. |
endLongitude | BigDecimal | Optional. End longitude of the trip ([-180.0; +180.0]). |
endLatitude | BigDecimal | Optional. End latitude of the trip ([-90.0; +90.0]). |
roundTrip | Boolean | Optional. Whether this was a round trip; if yes, the returned distance will be multiplied by two. Only applicable if no waypoints have been defined. |
waypoints | Waypoint[] | Optional. Waypoints located between the origin and the destination. Can only have up to 10 waypoints. |
Response body
The computed distance.
field | type | description |
---|---|---|
start | Place | |
start.area1 | String | |
start.area2 | String | |
start.country | String | |
start.externalId | String | |
start.formattedAddress | String | |
start.latitude | BigDecimal | |
start.locality | String | |
start.longitude | BigDecimal | |
start.postalCode | String | |
start.postalTown | String | |
start.postBox | String | |
start.provider | PlaceProvider | |
start.query | String | |
start.route | String | |
start.streetAddress | String | |
start.streetNumber | String | |
end | Place | |
end.area1 | String | |
end.area2 | String | |
end.country | String | |
end.externalId | String | |
end.formattedAddress | String | |
end.latitude | BigDecimal | |
end.locality | String | |
end.longitude | BigDecimal | |
end.postalCode | String | |
end.postalTown | String | |
end.postBox | String | |
end.provider | PlaceProvider | |
end.query | String | |
end.route | String | |
end.streetAddress | String | |
end.streetNumber | String |
PlaceProvider
value | description |
---|---|
Compute trip distance
Computes the distance of a simple trip, with two waypoints.
Request
POST /api/tools/v1/tools/mileage/trip
Request body
The coordinates of the waypoints.
field | type | description |
---|---|---|
startAddress | String | Optional. Start address of the trip. If missing, then start longitude and latitude must be filled. |
startLongitude | BigDecimal | Optional. Start longitude of the trip ([-180.0; +180.0]). |
startLatitude | BigDecimal | Optional. Start latitude of the trip ([-90.0; +90.0]). |
endAddress | String | Optional. End address of the trip. If missing, then end longitude and latitude must be filled. |
endLongitude | BigDecimal | Optional. End longitude of the trip ([-180.0; +180.0]). |
endLatitude | BigDecimal | Optional. End latitude of the trip ([-90.0; +90.0]). |
roundTrip | Boolean | Optional. Whether this was a round trip; if yes, the returned distance will be multiplied by two. Only applicable if no waypoints have been defined. |
waypoints | Waypoint[] | Optional. Waypoints located between the origin and the destination. Can only have up to 10 waypoints. |
Response body
The computed distance.
See TripDistance
Shared resources
Advance imputation
When an expense is reimbursed to the user, some part of the reimbursable amount may have been paid already, in the form of advances provisioned by the organization to the user. This object helps track such pre-payments.
field | type | description |
---|---|---|
advanceId | String | The unique identifier of the advance provisioned by the organization to the user. An advance may be used to reimburse one or many expenses (if it is large enough). |
imputedAmount | BigDecimal | The amount imputed on the advance for this expense. For instance, if the user has been allocated an advance of 30\u20ac and now issues an expense of 10\u20ac, then the advance will be imputed for 10\u20ac (20\u20ac will remain available for other expenses). Expressed in the reimbursement currency, usually the master currency of the organization. |
AllowanceTemplate
Allowance template will be provided as a way to create an allowance, which is an expense with values filled from template at creation and not updatable after (like name, total, category, ...).
User will be able to update expense time, explanation, custom fields, ...
Values are copied on expense creation, updating a template after will not affect existing expenses.
field | type | description |
---|---|---|
templateId | String | Template id, value must be passed when creating an allowance expense. |
labelsPerLanguage | Map<String,String> | The labels of the allowance template, per language, as displayed to front clients (web application, mobile applications). |
total | BigDecimal | The total amount of the allowance. |
currency | String | The currency of the total amount. (EUR, USD, ...) |
country | String | The country of the expense. (FR, US, ...) |
category | String | The category of the expense. |
paymentMethodId | String | The identifier of the payment method which was used to pay the expense (for instance a credit card). Payment methods are declared on the groups of the organization. |
order | int | Template order in the front selection list. |
disabled | Boolean | Disable the template, making creation of new expense from it impossible. |
requireReceipt | Boolean | User must add a receipt with the allowance (default false). If no receipt is required, the category icon will be used instead. |
emptyDate | Boolean | Empty expense date on page load (if false, the current date is pre-filled) |
creationCondition | ScopeCondition | Allow to manage the availability of the template for the users, using advanced conditions |
Bookkeeper
A bookkeeper
is an accounting company, which manages the accounts of client companies, such as liberal professionals.
It is structured into a hierarchy of bookkeeper groups
, each group representing an operational team of the bookkeeper.
Most of the time, a bookkeeper only needs a single team, i.e. the default root group
.
field | type | description |
---|---|---|
id | String | Unique identifier of the bookkeeper in Jenji (a UUID). |
name | String | The name of the company. |
jenjiOrganizationId | String | The bookkeeper may also use Jenji as a service for the management of its own expenses. If so, this field contains the identifier of its Jenji organization. |
masterBookkeeperId | String | This field contains the identifier of the master bookkeeper which manages the bookkeeper, if there is one. The master bookkeeper may perform most operations in the name of its managed bookkeeper. |
clientOptions | BookkeeperClientOptions | Newly-added clients are declared with default options, which are reported below. To date, these options may not be changed by API, but only through our Support. |
groups | BookkeeperGroup[] | The hierarchy of groups of the bookkeeper (each group represents an operational team of the bookkeeper). The top group is named "root group", it is the default group and it may not be deleted. |
createdAt | OffsetDateTime | Timestamp of creation of the bookkeeper. |
updatedAt | OffsetDateTime | Timestamp of last update of the bookkeeper. This timestamp is updated if any header data, or data of the root group, are modified. It is not updated if a subgroup has changed. |
BookkeeperClient
A bookkeeper may manage the expenses of an organization. In such a case, the organization becomes the client of the bookkeeper, and this entity represents the link between the bookkeeper and the organization, as well as its characteristics.
field | type | description |
---|---|---|
bookkeeperId | String | The identifier of bookkeeper party. |
organizationId | String | The identifier of organization managed by the bookkeeper. |
internalId | String | Optional field, an internal id for the contract in the bookkeeper information system. |
explanation | String | Optional field, any form of comment from the bookkeeper to clarify the nature of the contract, or any worthwhile information to pay attention to. |
BookkeeperClientOptions
Technical options associated to a client of a bookkeeper.
These options are currently readonly (contact our Support if you want to change them). They are defined in the organization template chosen by the bookkeeper when creating a new client.
field | type | description |
---|---|---|
clientsBilledByJenji | boolean | The activity of an organization (expense management...) is billed by Jenji, either to the bookkeeper, or to the organization itself. If set to true, then the organization is billed directly. |
manageClientVault | boolean | Jenji offers a Vault service, which allows to safeguard the receipts of expenses for a certain number of years, in an official Vault, recognized by the Tax departments of the State Administration. If set to true, then the bookkeeper is allowed to manage the vault in the name of its client. |
enableClientVaultOnNewClient | boolean | Whether to enable automatically the client Vault when the bookkeeper creates a new organization. |
allowSoloPlanClient | boolean | Jenji offers many commercial plans, among which the SOLO (FREE) plan. This plan is free forever for our users, although it does not include all features of Jenji. If set to true, then the bookkeeper may create clients with a SOLO plan. |
mustUseTemplate | boolean | Is an org must be created with template ? If true, the template is mandatory. |
BookkeeperClientTemplate
A bookkeeper may need to create clients following the same template. This entity represents a client template that can be used as base to create organisations managed by the bookkeeper
field | type | description |
---|---|---|
bookkeeperId | String | The identifier of bookkeeper party. |
templateId | String | The identifier of template managed by the bookkeeper. |
internalId | String | Optional field, an internal id for the contract in the bookkeeper information system. |
explanation | String | Optional field, any form of comment from the bookkeeper to clarify the nature of the contract, or any worthwhile information to pay attention to. |
BookkeeperGroup
A group represents a team of the bookkeeper. It includes members of the team (users), and defines security rights.
field | type | description |
---|---|---|
id | String | Unique identifier of the group in Jenji (either "root" for the root group, or a UUID). |
name | String | The name of the team. In the case of a bookkeeper with only the default root group, this is the same as the company name. |
parentGroupId | String | Groups can be articulated together as a hierarchy. The parent group identifier references the parent group of this current group. All groups have a parent, except the root group which stands at the top, which has no parent (null). |
createdAt | OffsetDateTime | Timestamp of creation of the group. |
updatedAt | OffsetDateTime | Timestamp of last update of the group. |
BookkeeperUser
A user is a team member (e.g. a sales representative, an accountant...) of a bookkeeper group.
field | type | description |
---|---|---|
id | String | Unique identifier of the User in Jenji (UUID or email, depending on the original registration channel). |
bookkeeperId | String | Unique identifier of the bookkeeper to which the user belongs. |
groupId | String | Unique identifier of the group of the bookkeeper to which the user belongs. |
internalId | String | Optional field, containing the internal identifier of the user in the information system of the bookkeeper. This may help when querying the APIs and performing various mapping tasks. |
firstName | String | First name of the user, like "Alex" in "Alex Pence". |
lastName | String | Last name of the user, like "Pence" in "Alex Pence". |
updatedAt | OffsetDateTime | Timestamp of the last update of the user. |
createdAt | OffsetDateTime | Timestamp of the creation of the user. |
blockedAt | OffsetDateTime | Timestamp of the blocking of the user. This field is null when the user is not blocked. |
Category
A category is the primary analytic feature of an expense. It may for instance be a "meal" or an "hotel".
The system provides standard categories, but also allows organizations to define and use their own additional categories.
field | type | description |
---|---|---|
id | String | Identifier of the category. This is usually a code unique within the organization, either a standard code for a Jenji category, or a custom code for a custom category. |
disabled | Boolean | The category may be disabled, i.e. is not usable on new expenses. Previous expenses which reference this category may still use it. |
notSelectable | Boolean | The category is still valid, but not usable. |
labelsPerLanguage | Map<String,String> | The labels of the category, per language, as displayed to front clients (web application, mobile applications). Organization which define custom categories are encouraged to define labels for all the languages they manage. |
ocrMappedStandardCategories | String[] | List of standard category codes to map onto the custom category, when our AI-based agent analyzes a receipt and derives a standard category which has been replaced by a custom category by the organization. |
order | Integer | Order of the category for front clients. |
parentCategoryId | String | Categories may be hierarchical; child categories reference a parent category. |
iconId | String | The identifier of the icon used to display the category in front clients. |
colorId | String | The identifier of the color used to display the category in front clients. |
scopeCondition | ScopeCondition | Allow to manage the visibility of the category, using advanced conditions |
CompareMode
value | description |
---|---|
GT | Strictly greater than |
GE | Greater or equals |
LT | Strictly lesser than |
LE | Lesser or equals |
EQ | Equals |
CustomField
Custom fields are analytic fields freely defined by an organization, which may be filled in by a user when creating an expense.
field | type | description |
---|---|---|
key | String | This is the unique code of the custom field. |
type | String | The custom field may only contain values of the same type. Currently supported types include:
New types may be regularly added. |
minimumValue | BigDecimal | Only for custom fields of type NUMBER or LONG. The minimum value allowed for this custom field. |
maximumValue | BigDecimal | Only for custom fields of type NUMBER or LONG. The maximum value allowed for this custom field. |
listId | String | Only for custom fields of type LIST, generated by the backend. ID required to manipulate the list of options associated with this custom field. |
required | Boolean | Whether the custom field is mandatory when creating an expense. |
labelsPerLanguage | Map<String,String> | Localized labels of the custom fields. Organizations are encouraged to provide labels for each language that they manage. |
editableByGroups | String[] | List of identifiers of organization groups which may use and edit the values of a custom field. |
visibleByGroups | String[] | List of identifiers of organization groups which may use and view (but not edit) the values of a custom field. Groups that may edit a custom field, may also view it. |
order | Integer | Order of the custom field, for front clients. |
visibleScopeCondition | ScopeCondition | Allow to manage the visibility using advanced conditions |
configuredByAPI | Boolean | Whether this custom field may be configured, updated or deleted only by external API calls, and not manually within the app by an organization user. Setting this flag to true is an equivalent of setting the 3 flags {disableConfiguration, disableOptionConfiguration, disableDeletion} to true. This flag takes precedence over the other flags. |
disableConfiguration | Boolean | Disable the button to configure the custom field within the app |
disableOptionConfiguration | Boolean | Disable the button to configure custom field options (for collection types) within the app |
disableDeletion | Boolean | Disable the button to delete the custom field within the app |
validation | CustomFieldValidation | validation defines rules for custom field values. |
CustomFieldType
value | description |
---|---|
DATE | |
LONG | |
LIST | |
LONGTEXT | |
NUMBER | |
STRING | |
STRING_SET | |
TIME_HH_MM | |
EXTERNAL | |
PLACE | |
BOOLEAN | |
FILES |
CustomFieldValidation
Custom fields validation defines rules for custom field values.
field | type | description |
---|---|---|
minimumValue | BigDecimal | Applicable to custom fields of type NUMBER or LONG: minimum allowed value. |
maximumValue | BigDecimal | Applicable to custom fields of type NUMBER or LONG: maximum allowed value. |
CustomOption
field | type | description |
---|---|---|
id | String | This is the unique identifier of the custom option. |
labelsPerLanguage | Map<String,String> | Localized labels of the custom option. Organizations are encouraged to provide labels for each language they manage. |
extra | String | A field to hold extra information about the option, it can hold a complete JSON object. |
accountingCode | String | This is a code, used in accounting exports |
disabled | Boolean | The option may be disabled. It acts as a logical deletion, e.g. existing items still reference the option, but new ones cannot. |
scope | String | scope : the option must be seen by a user, a group or user owning custom field. For user, specify user Id. For group, specify group Id. For user custom field, specify user custom field value. The setup of the custom field is by made by your project manager. Feel free to question him on these options. Optional. |
scopeCondition | ScopeCondition | scopeCondition : the option must be activate on calculated condition. The setup of the custom field is by made by your project manager. Feel free to question him on these options. Optional. |
DailyUserActivity
Aggregated statistics about actions in Jenji for a user and a day.
field | type | description |
---|---|---|
userId | String | The user identifier. Format: UUID v4. |
day | String | The day of activity. Format: YYYY-MM-DD. |
organizationId | String | The organization identifier. Format: UUID v4. |
created | int | The number of expenses created that day. Increased as soon as the user creates a standard, mileage or allowance expense. |
checked | int | In organizations with the compliance step enabled, incremented as soon as the user marks an expense as 'compliant' or 'not compliant'. For organizations with a custom expense workflow, incremented when the user performs an intermediary validation step. Only possible for users with expense verification rights or equivalent profiles. |
decided | int | Incremented as soon as the user marks an expense as accepted or rejected. For organizations with a custom expense workflow, incremented when the user performs the final validation step on an expense. Only possible for users with expense validation rights or equivalent profiles. |
accounted | int | Incremented when an accounting export is marked as 'accounted'. Every expense in the export increments this counter by 1. Only possible for users with accounting rights. |
paid | int | Incremented when a payroll export is marked as 'reimbursed'. Every expense in the export increments this counter by 1. Only possible for users with accounting rights. |
deleted | int | Incremented as soon as the user changes the state of an expense to 'DELETED'. Since Jenji only performs logical deletions, multiple delete/undelete operations on a same expense will increment this counter multiple times. |
ignored | int | The number expense actions that would usually be billed but are ignored because of special organization rules. This field can safely be ignored if no such rules have been contractually defined. |
Delegation
A delegation represents the right for a user to act as another user (impersonation), to create or edit expenses for this user, or perform some administrative tasks, such as verifying or validating an expense.
A group delegation represents the right of a user to act on behalf of all users belonging to a referenced group.
field | type | description |
---|---|---|
id | String | The delegation identifier, autogenerated with user id or group id if not present |
userId | String | The identifier of the user on whom the current user is given a delegation. |
groupId | String | The identifier of the group on which the current user is given a delegation. All users of that group may be impersonated. |
permission | DelegationPermission | The permission type granted by the delegation (read-only, write etc). |
start | LocalDate | The date from which the delegation is valid. Only applies to user delegations. |
end | LocalDate | The date after which the delegation ends. Only applies to user delegations. |
DelegationPermission
Qualifies which actions a user can do on behalf of a delegated user.
value | description |
---|---|
READ | The user is granted a read-only access to the delegated user. |
WRITE | The user is granted all rights on the delegated user, i.e. can perform any action on behalf of the delegated user. |
PERSONAL | The user is granted restricted rights on the delegated user, namely the ability to view, create and edit expenses only. |
NONE | The user is granted no right at all. |
DistanceUnit
Distance unit.
value | description |
---|---|
KM | Kilometers |
MI | miles |
Expense
3 variants:
StandardExpense
A standard expense, with a receipt scanned and uploaded to Jenji.
field | type | description |
---|---|---|
id | String | Unique identifier of the expense in Jenji (a UUID). |
userId | String | Unique identifier of the organization user for which the expense applies (either an email or a UUID, depending on the acquisition channel). |
organizationId | String | Unique identifier of the organization to which the expense user belongs. This identifier is determined by the routing rules declared for the organization, and is set right after the expense creation. |
time | LocalDate | Day on which the expense occurred (imputation). |
explanation | String | Explanation for the expense, provided by the user who has created the expense. This explanation will be read by the manager who approves the expense. |
tags | String[] | Simple labels, freely settable by the user who creates the expense. Tags may be used to search and find expenses easily in the various front clients (web application, mobile applications). |
total | BigDecimal | The total amount of the expense, including taxes. |
currency | String | The currency of the total amount. This currency should match the one specified in the receipt, when there is a receipt available. |
country | String | The country in which the expense occurred. |
billable | Boolean | Whether the expense may be billed to another party. |
reimbursable | Boolean | Whether the expense may be reimbursed to the user who has created it. |
attendees | String[] | The expense may be related to an event to which many users of the organization have attended. In such cases, the list of attendees contain the identifiers or these users. |
state | String | The state the expense is in, when the query is performed. The state may vary across organizations, depending on whether they have defined a custom workflow for expense management. |
label | String | The vendor of the service for which the expense has occurred (e.g. the name of a restaurant, a taxi company...). |
customFields | Map<String,Object> | Custom fields are defined by organizations, to help classify an expense for analytic purposes. This fields maps values for all required custom fields. |
reimbursement | Reimbursement | Contains all the details of the reimbursement of the expense to the user. This field is only set after the expense has been validated. |
createdAt | OffsetDateTime | Timestamp at which the expense was created. |
createdWith | String | Medium through which the expense was created (mobile phone, web service...). |
updatedAt | OffsetDateTime | Timestamp at which the expense was last updated. |
validatedBy | String | Identifier of the user who has validated the expense (standard workflow). |
validatedAt | OffsetDateTime | Timestamp at which the expense was validated (standard workflow). |
accountedBy | String | Identifier of the user who has exported the expense for accounting (standard workflow). |
accountedAt | OffsetDateTime | Timestamp at which the expense was accounted for (standard workflow). |
paidBy | String | Identifier of the user who has authorized the reimbursement of the expense (standard workflow). |
paidAt | OffsetDateTime | Timestamp at which the expense was reimbursed to the user (standard workflow). |
checkedBy | String | Identifier of the user who has checked the expense (standard workflow). |
checkedAt | OffsetDateTime | Timestamp at which the expense was checked (standard workflow). |
deletedBy | String | Identifier of the user who has deleted the expense (standard workflow). |
deletedAt | OffsetDateTime | Timestamp at which the expense was deleted (standard workflow). |
warnings | ExpenseWarning[] | List of the expense warnings (duplicate, invalid receipt...). |
lastAction | String | |
lastActionBy | String | |
lastActionAt | OffsetDateTime | |
lastActionComment | String | |
category | String | An expense is attached to a primary category, like "meal" or "hotel". We propose standard categories to begin with, but the organization may freely add custom categories if it so wishes. Categories are declared on the organization itself. |
receiptKey | String | The key of the receipt, obtained when uploading the receipt to the Jenji Storage. Once the receipt has been uploaded, it may not be changed. |
invalidReceipt | Boolean | Whether the receipt was deemed invalid during our processing. |
paymentMethodId | String | The identifier of the payment method which was used to pay the expense (for instance a credit card). Payment methods are declared on the groups of the organization. |
totalWithoutTax | BigDecimal | The total before tax. |
totalInMasterCurrency | BigDecimal | The total expressed in the master currency of the organization (may differ from the currency of the expense). The conversion is made with a standard exchange rate, unless the organization has specified custom conversion policies in its settings. |
totalWithoutTaxInMasterCurrency | BigDecimal | The total without tax, expressed in the master currency of the organization (may differ from the currency of the expense). |
totalConversionRate | BigDecimal | The exchange rate used to convert the amounts from the expense currency to the master currency of the organization. |
taxes | Tax[] | The various taxes applied to the original amount. |
type | ExpenseType |
Mileage
An expense resulting of a travel made by a user, with a personal vehicle.
field | type | description |
---|---|---|
id | String | Unique identifier of the expense in Jenji (a UUID). |
userId | String | Unique identifier of the organization user for which the expense applies (either an email or a UUID, depending on the acquisition channel). |
organizationId | String | Unique identifier of the organization to which the expense user belongs. This identifier is determined by the routing rules declared for the organization, and is set right after the expense creation. |
time | LocalDate | Day on which the expense occurred (imputation). |
explanation | String | Explanation for the expense, provided by the user who has created the expense. This explanation will be read by the manager who approves the expense. |
tags | String[] | Simple labels, freely settable by the user who creates the expense. Tags may be used to search and find expenses easily in the various front clients (web application, mobile applications). |
total | BigDecimal | The total amount of the expense, including taxes. |
currency | String | The currency of the total amount. This currency should match the one specified in the receipt, when there is a receipt available. |
country | String | The country in which the expense occurred. |
billable | Boolean | Whether the expense may be billed to another party. |
reimbursable | Boolean | Whether the expense may be reimbursed to the user who has created it. |
attendees | String[] | The expense may be related to an event to which many users of the organization have attended. In such cases, the list of attendees contain the identifiers or these users. |
state | String | The state the expense is in, when the query is performed. The state may vary across organizations, depending on whether they have defined a custom workflow for expense management. |
label | String | The vendor of the service for which the expense has occurred (e.g. the name of a restaurant, a taxi company...). |
customFields | Map<String,Object> | Custom fields are defined by organizations, to help classify an expense for analytic purposes. This fields maps values for all required custom fields. |
reimbursement | Reimbursement | Contains all the details of the reimbursement of the expense to the user. This field is only set after the expense has been validated. |
createdAt | OffsetDateTime | Timestamp at which the expense was created. |
createdWith | String | Medium through which the expense was created (mobile phone, web service...). |
updatedAt | OffsetDateTime | Timestamp at which the expense was last updated. |
validatedBy | String | Identifier of the user who has validated the expense (standard workflow). |
validatedAt | OffsetDateTime | Timestamp at which the expense was validated (standard workflow). |
accountedBy | String | Identifier of the user who has exported the expense for accounting (standard workflow). |
accountedAt | OffsetDateTime | Timestamp at which the expense was accounted for (standard workflow). |
paidBy | String | Identifier of the user who has authorized the reimbursement of the expense (standard workflow). |
paidAt | OffsetDateTime | Timestamp at which the expense was reimbursed to the user (standard workflow). |
checkedBy | String | Identifier of the user who has checked the expense (standard workflow). |
checkedAt | OffsetDateTime | Timestamp at which the expense was checked (standard workflow). |
deletedBy | String | Identifier of the user who has deleted the expense (standard workflow). |
deletedAt | OffsetDateTime | Timestamp at which the expense was deleted (standard workflow). |
warnings | ExpenseWarning[] | List of the expense warnings (duplicate, invalid receipt...). |
lastAction | String | |
lastActionBy | String | |
lastActionAt | OffsetDateTime | |
lastActionComment | String | |
distance | BigDecimal | The distance travelled by the user, required to compute the amount to reimburse. |
computedDistance | BigDecimal | The distance computed via Google Maps. |
distanceUnit | DistanceUnit | The unit of the distance (km or mi, default is km). |
numberOfPassengers | Integer | The number of passengers transported by the user on his/her trip. |
vehicleId | String | The identifier of the personal vehicle of the user, defined in his/her profile. |
waypoints | Waypoint[] | The waypoints describes the different points of the journey made by the user. Each waypoint may include geographical coordinates, or addresses. |
type | ExpenseType |
Allowance
An allowance is an expense which amount (among other things) is fixed, based on company rules. For instance, one may receive an allowance of 15\u20ac for lunches.
field | type | description |
---|---|---|
id | String | Unique identifier of the expense in Jenji (a UUID). |
userId | String | Unique identifier of the organization user for which the expense applies (either an email or a UUID, depending on the acquisition channel). |
organizationId | String | Unique identifier of the organization to which the expense user belongs. This identifier is determined by the routing rules declared for the organization, and is set right after the expense creation. |
time | LocalDate | Day on which the expense occurred (imputation). |
explanation | String | Explanation for the expense, provided by the user who has created the expense. This explanation will be read by the manager who approves the expense. |
tags | String[] | Simple labels, freely settable by the user who creates the expense. Tags may be used to search and find expenses easily in the various front clients (web application, mobile applications). |
total | BigDecimal | The total amount of the expense, including taxes. |
currency | String | The currency of the total amount. This currency should match the one specified in the receipt, when there is a receipt available. |
country | String | The country in which the expense occurred. |
billable | Boolean | Whether the expense may be billed to another party. |
reimbursable | Boolean | Whether the expense may be reimbursed to the user who has created it. |
attendees | String[] | The expense may be related to an event to which many users of the organization have attended. In such cases, the list of attendees contain the identifiers or these users. |
state | String | The state the expense is in, when the query is performed. The state may vary across organizations, depending on whether they have defined a custom workflow for expense management. |
label | String | The vendor of the service for which the expense has occurred (e.g. the name of a restaurant, a taxi company...). |
customFields | Map<String,Object> | Custom fields are defined by organizations, to help classify an expense for analytic purposes. This fields maps values for all required custom fields. |
reimbursement | Reimbursement | Contains all the details of the reimbursement of the expense to the user. This field is only set after the expense has been validated. |
createdAt | OffsetDateTime | Timestamp at which the expense was created. |
createdWith | String | Medium through which the expense was created (mobile phone, web service...). |
updatedAt | OffsetDateTime | Timestamp at which the expense was last updated. |
validatedBy | String | Identifier of the user who has validated the expense (standard workflow). |
validatedAt | OffsetDateTime | Timestamp at which the expense was validated (standard workflow). |
accountedBy | String | Identifier of the user who has exported the expense for accounting (standard workflow). |
accountedAt | OffsetDateTime | Timestamp at which the expense was accounted for (standard workflow). |
paidBy | String | Identifier of the user who has authorized the reimbursement of the expense (standard workflow). |
paidAt | OffsetDateTime | Timestamp at which the expense was reimbursed to the user (standard workflow). |
checkedBy | String | Identifier of the user who has checked the expense (standard workflow). |
checkedAt | OffsetDateTime | Timestamp at which the expense was checked (standard workflow). |
deletedBy | String | Identifier of the user who has deleted the expense (standard workflow). |
deletedAt | OffsetDateTime | Timestamp at which the expense was deleted (standard workflow). |
warnings | ExpenseWarning[] | List of the expense warnings (duplicate, invalid receipt...). |
lastAction | String | |
lastActionBy | String | |
lastActionAt | OffsetDateTime | |
lastActionComment | String | |
category | String | An expense is attached to a primary category, like "meal" or "hotel". We propose standard categories to begin with, but the organization may freely add custom categories if it so wishes. Categories are declared on the organization itself. |
receiptKey | String | The key of the receipt, obtained when uploading the receipt to the Jenji Storage. Once the receipt has been uploaded, it may not be changed. |
invalidReceipt | Boolean | Whether the receipt was deemed invalid during our processing. |
paymentMethodId | String | The identifier of the payment method which was used to pay the expense (for instance a credit card). Payment methods are declared on the groups of the organization. |
totalWithoutTax | BigDecimal | The total before tax. |
totalInMasterCurrency | BigDecimal | The total expressed in the master currency of the organization (may differ from the currency of the expense). The conversion is made with a standard exchange rate, unless the organization has specified custom conversion policies in its settings. |
totalWithoutTaxInMasterCurrency | BigDecimal | The total without tax, expressed in the master currency of the organization (may differ from the currency of the expense). |
totalConversionRate | BigDecimal | The exchange rate used to convert the amounts from the expense currency to the master currency of the organization. |
taxes | Tax[] | The various taxes applied to the original amount. |
templateId | String | An allowance always references a template, where fixed parts of the expense are defined. |
type | ExpenseType |
ExpenseBaseField
value | description |
---|---|
TOTAL | Expense total |
TOTAL_WOT | Expense total without tax |
CATEGORY | Expense category code |
EXPENSE_TYPE | Expense type mileage / allowance / per-diem / classic |
CURRENCY | Expense currency code (EUR, USD, ...) |
COUNTRY | Expense country code (FR, US, ...) |
META_STATE | Expense meta-state (Classic states + custom ones) |
PAYMENT_METHOD | Expense payment method id |
ALLOWANCE_ID | Allowance template id |
BILLABLE | Billable flag |
ATTENDEES | Attendees list (for empty conditions) |
ExpenseRequest
field | type | description |
---|---|---|
id | String | Unique identifier of the expense request in Jenji (a UUID). |
shortId | String | Unique short Id identifier |
label | String | Label of expense request |
type | String | Type of expense request |
userId | String | Unique identifier of the organization user for which the expense request applies (either an email or a UUID, depending on the acquisition channel). |
state | String | State of the expense request |
comment | String | Explanation for the expense expense request, provided by the user who has created the expense. This explanation will be read by the manager who approves the expense. |
expenses | String[] | Expenses Id of linked expenses. |
creationDate | OffsetDateTime | Creation date of expense Request. |
customFields | Map<String,Object> | Custom fields are defined by organizations, to help classify an expense request for analytic purposes. This fields maps values for all required custom fields. |
files | ExpenseRequestFile[] | Expense request attached files. |
ExpenseRequestFile
field | type | description |
---|---|---|
name | String | Real file name (displayed in UX). |
file | String | File reference in Jenji storage system. |
ExpenseType
An expense may be of a certain type, and some fields of an expense depend on the declared type (such as the distance in the case of a mileage expense).
value | description |
---|---|
STANDARD | Standard expense (code S). Expense with a receipt. |
MILEAGE | Mileage expense (code M). For travels made with a personal vehicle, with specific company/state policies. |
ALLOWANCE | Allowance declaration (code A). |
PERDIEM | Per-Diem allowance declaration (code P). |
ExpenseWarning
An expense warning describes a custom rule to be applied to an expense, to check some of its state. For instance, a "duplicate" warning tells when 2 expenses of the same amount are created on the same day.
field | type | description |
---|---|---|
warningRuleId | String | The identifier of the warning rule. Either the identifier of a custom rule (a UUID), or a reserved rule identifier (e.g. "duplicate"). |
userId | String | Identifier of the user who own the warning (user of the targeted expense) |
time | LocalDate | Day on which the expense owning the warning occurred. |
updatedAt | OffsetDateTime | Timestamp of the update of the warning. |
code | String | The custom code chosen when creating the warning rule. |
labelsPerLanguage | Map<String,String> | Custom labels for the warning, by language code. Custom labels are optional, they are only set for warnings generated by certain warning rules. When missing, default labelling algorithms should be applied, e.g. derive appropriate labels from the warning code, or from the default labels of the associated warning rule. |
isPreventingValidation | Boolean | Indicates whether this warning should prevent the validation of the expense/request or not |
mutedAt | OffsetDateTime | Timestamp of the muting of the warning. |
mutedBy | String | Identifier of the user who has muted the warning. |
linkedExpensesIds | String[] | Identifiers of the expenses that are related to the warning. |
Organization
An organization is an operating company, for which we want to track expenses. Members of the organization, such as sales representatives, managers, accountants, may gain access to the organization as organization users, to act at the many steps of the workflow of expense management.
field | type | description |
---|---|---|
id | String | Unique identifier of the Organization in Jenji (UUID). |
name | String | Name of the organization, usually the name of the company. |
plan | String | Commercial plan of the organization. One of:
|
createdBy | String | Medium through which the organization was created (backend, mobile application...). |
createdAt | OffsetDateTime | Timestamp of the creation of the organization. |
masterCurrency | String | The reporting currency of the organization. Expenses may be expressed in local currencies, different from the organization currency, but amounts are always converted and reported to the currency of the organization. |
masterCountry | String | The reporting country of the organization. |
masterLanguage | String | The reporting language of the organization. |
masterDistanceUnit | DistanceUnit | Distance unit for the organization. Default is km. |
states | String[] | List of the organization states. From:
|
availableLanguages | String[] | All languages usable by the organization. |
categories | Category[] | All categories allowed for the organization. May contain standard categories, as well as custom categories, created by the organization. |
groups | OrganizationGroup[] | The hierarchy of groups of the organization (each group represents an operational team of the organization). The top group is named "root group", it is the default group and it may not be deleted. |
userCustomFields | CustomField[] | List of custom fields which values may be customized for each user. |
groupCustomFields | CustomField[] | List of custom fields which values may be customized for each group. |
expenseCustomFields | CustomField[] | List of default custom fields usable in an expense. Other custom fields may be declared on the expense, depending on the logged user and his/her group. |
expenseRequestCustomFields | CustomField[] | List of default custom fields usable in an expense request. |
advanceCustomFields | CustomField[] | List of default custom fields usable in an advance. |
vehicleCustomFields | CustomField[] | List of default custom fields usable in a vehicle. |
features | Map<String,Boolean> | List of technical features currently active for the organization. Features may not be enabled or disabled by API, please contact our Support if you wish to change them. |
templateId | String | ID of the last applied template on the organization. |
OrganizationCommunication
Any business message defined by an organization group manager to inform all users of that group. ex: 'Please enter all your expenses before the 25th of the month to be reimbursed'.
field | type | description |
---|---|---|
id | String | Unique identifier of the communication in Jenji (UUID). |
code | String | Code freely defined by a manager to identify a specific communication in a human readable way. |
groupId | String | Identifier of the organization group for which the communication has been defined. |
messagesPerLanguage | Map<String,String> | The messages of the communication, per language, as displayed to front clients (web application, mobile applications). |
level | String | Level of the communication : INFO, WARNING, ERROR, SUCCESS. |
startDate | OffsetDateTime | Start date of the communication. If null, the communication is considered as started. |
endDate | OffsetDateTime | End date of the communication. If null, the communication is considered still running. |
updatedAt | OffsetDateTime | Timestamp of the last modification of the communication. |
OrganizationGroup
A group represents a team of the organization. It includes members of the team (users), and defines security rights.
field | type | description |
---|---|---|
id | String | Unique identifier of the group in Jenji (UUID). |
internalId | String | Optional field, an internal id for the team, in the organization information system. |
name | String | The name of the group / team. |
parentGroupId | String | Groups form a hierarchy, topped by a "root group". All groups have a parent group, except the root group. |
paymentMethods | PaymentMethod[] | List of payment methods usable by the users of the group, when they create expenses. |
customFieldValues | Map<String,?> | List of custom field values, by custom field code. The serialized expression for values depends on the type of the custom field. |
createdAt | OffsetDateTime | Timestamp of the creation the group. |
updatedAt | OffsetDateTime | Timestamp of the last update of the group. |
PaymentMethod
Payment method used by the organization user to pay for the expense, like a personal credit card.
field | type | description |
---|---|---|
id | String | Unique identifier of the payment method in Jenji (UUID). |
label | String | The label of the payment method, to help the user select the appropriate method when creating the expense. |
labelsPerLanguage | Map<String,String> | The labels of the payment method, per language, as displayed to front clients (web application, mobile applications). |
code | String | The code of the payment method, available in various exports. |
reimbursable | Boolean | Whether any expense made with this payment is reimbursable. A company credit card, for instance, would not incur reimbursable expenses, while a personal credit card would require reimbursements. |
dissociated | Boolean | Whether the payment method is dissociated. |
disabled | Boolean | Whether the payment method is now disabled, i.e. may not be used on new expenses. |
transactionProvider | String | A payment method may be associated with a transaction provider, such as a bank. Jenji offers many integration features with existing banks, whereby an organization may allow Jenji to retrieve bank transactions from its bank, so as to automatically reconcile an expense with a matching bank transaction. |
ReceiptDownload
A secure URL from which the receipt of an expense may be downloaded. This URL remains valid for a few minutes only.
field | type | description |
---|---|---|
downloadUrl | String | The url to download the receipt. |
ReceiptUpload
A secure URL to where a receipt may be uploaded, as well as a technical key pointing to the location, to be referenced into the expense. This URL remains valid for a few minutes only.
field | type | description |
---|---|---|
uploadUrl | String | The url to upload the receipt. |
key | String | The key to link the receipt and the expense. |
Reimbursement
Contains all details of the actual reimbursement of an expense to the organization user.
The amount reimbursed to the user is computed as:
- The total amount of the expense,
- Possibly capped by organization reimbursement policies, yielding a reimbursable amount,
- Possibly decremented by amounts already paid to the user by the organization as advances, yielding a due amount.
field | type | description |
---|---|---|
reimbursementCurrency | String | The currency of the reimbursed amount and advance imputations. This is usually the master currency of the organization, unless overridden by/for a certain user. |
reimbursableAmount | BigDecimal | This is the amount of the expense which is reimbursable to the user after the organization reimbursement policies have been applied. It is usually the total amount of the expense, unless the organization has defined a maximum reimbursable amount. For instance, a user may have dinner for 25\u20ac, but the company rules state that only up to 20\u20ac would be reimbursed for dinners. The reimbursable amount thus becomes 20\u20ac, and not 25\u20ac. |
advances | Advance imputation[] | Some advances may be paid to the user before any expense is done. When an expense is reimbursed, the amounts originally paid as advances are subtracted from the reimbursable amount. This field holds the details of the imputations on the advances provisioned to the user. |
dueAmount | BigDecimal | This represents what the company still owes to the user, after advances have been subtracted from the reimbursable amount. |
ScopeCondition
Base interface for all scope condition.
All objects must have a type
condition with a valid constant. The type defines which class is instantiated and which
properties are available. Type naming convention are the class name without the ScopeCondition
in upper snake case.
ie: AndScopeCondition -> AND, HasAnyProScopeCondition -> HAS_ANY_PRO
22 variants:
AndScopeCondition
Is true if all condition in conditions
attribute are true.
Will return false if conditions list is empty
field | type | description |
---|---|---|
conditions | ScopeCondition[] | Conditions to evaluate |
OrScopeCondition
Is true if one condition in conditions
attribute is true.
Will return false if conditions list is empty
field | type | description |
---|---|---|
conditions | ScopeCondition[] | Conditions to evaluate |
UcfEqScopeCondition
Is true if user custom field is equals to value
.
For multi list custom fields, it is true if the list contains value
field | type | description |
---|---|---|
code | String | User custom field code |
value | String | User custom field required value. It is always a String even for number custom fields. For boolean, use true or false . |
UcfEmptyScopeCondition
Is true if user custom field is null or empty
field | type | description |
---|---|---|
code | String | User custom field code |
UcfNotEmptyScopeCondition
Is true if user custom field is not empty
field | type | description |
---|---|---|
code | String | User custom field code |
HasAnyProScopeCondition
Is true if user has at least one of the profiles specified. See your organization configuration for available profiles.
field | type | description |
---|---|---|
profiles | String[] |
IsAdminScopeCondition
Is true if the user is administrator of any group
field | type | description |
---|---|---|
isAdmin | Boolean | null is considered equals to true |
IsInGroupScopeCondition
Is true if the user is in one of the group specified
field | type | description |
---|---|---|
groups | String[] |
IsAccountantScopeCondition
Is true if the user is accountant of any group
field | type | description |
---|---|---|
isAccountant | Boolean | null is considered equals to true |
IsCheckerScopeCondition
Is true if the user is checker of any group
field | type | description |
---|---|---|
isChecker | Boolean | null is considered equals to true |
IsManagerScopeCondition
Is true if the user is manager of any group
field | type | description |
---|---|---|
isManager | Boolean | null is considered equals to true |
NotScopeCondition
Is true if condition
is false
field | type | description |
---|---|---|
condition | ScopeCondition |
TrueScopeCondition
Is always true
field | type | description |
---|
FalseScopeCondition
Is always false
field | type | description |
---|
EcfEqScopeCondition
Is true if expense custom field is equals to specified value
field | type | description |
---|---|---|
code | String | |
value | String |
EcfCompareScopeCondition
This scope condition can compare the customField (reference by code) value :
- With a hard coded value : The scope condition is true if the customField (number custom field, referenced by the "code" attribute) value is greater/lower/equal (based on selected "mode") than/to the specified value attribute to use this mode, you need to specify the attributes "code","value", "dataType" and "mode" attributes (and only those ones) * Json example : * { * code : "customField1" * value : 3 * dataType : "NUMBER" * mode : "GT" * } * will be true if * customField1 value > 3
- With other customField value : The scope condition is true if the customField (number custom field, referenced by the "code" attribute) value is greater/lower/equal (based on selected "mode") than/to the "compareTo" customField value. The 2 compared custom fields (referenced by "code" and "compareToCode") must - both exist on org - be of same type - be of type date, number or long - be from the same entity : for exemple, you can not compare an ECF to an UCF Json example : { code : "customField1" compareToCode : "customField2" mode : "GT" } will be true if customField1 value > customField2 value
field | type | description |
---|---|---|
code | String | |
compareToCode | String | |
value | Object | |
mode | CompareMode | |
dataType | CustomFieldType |
EcfEmptyScopeCondition
Is true is an expense custom field is empty
field | type | description |
---|---|---|
code | String |
EcfNotEmptyScopeCondition
Is true is an expense custom field is filled
field | type | description |
---|---|---|
code | String |
EbfEqScopeCondition
Is true if expense base field is equals to specified value
field | type | description |
---|---|---|
field | ExpenseBaseField | |
value | String |
EbfCompareScopeCondition
Is true expense base field is greater/lower (based on selected mode) than the specified value
(Works only on total and total without tax)
field | type | description |
---|---|---|
field | ExpenseBaseField | |
value | BigDecimal | |
mode | CompareMode |
EbfEmptyScopeCondition
Is true is an expense base field is empty
field | type | description |
---|---|---|
field | ExpenseBaseField |
EbfNotEmptyScopeCondition
Is true is an expense base field is filled
field | type | description |
---|---|---|
field | ExpenseBaseField |
Tax
An expense may be eligible to different taxes.
field | type | description |
---|---|---|
baseAmount | BigDecimal | The base amount eligible to the tax. May be part or all of the total without tax. |
rate | BigDecimal | The tax rate to apply on the eligible amount. |
amount | BigDecimal | The resulting tax amount. |
TripDistance
An estimation of the distance travelled for a given trip, with a set of waypoints.
field | type | description |
---|---|---|
waypoints | Waypoint[] | All waypoints of the trip, including the origin and the destination. |
distance | BigDecimal | Computed distance, always expressed in kilometers. |
User
An organization user, or simply "user", belongs to a group of the organization. Users work at the different steps of the expense workflow, creating expenses, validating them or authorizing reimbursements.
field | type | description |
---|---|---|
id | String | Unique identifier of the User in Jenji (UUID or email, depending on the acquisition channel). |
login | String | Login used by the user to authenticate to Jenji. |
String | Email address at which the user may be contacted, to receive technical notifications. | |
firstName | String | First name of the user, like "Alex" in "Alex Pence". |
lastName | String | Last name of the user, like "Pence" in "Alex Pence". |
organizationId | String | Identifier of the organization to which the user belongs. |
groupId | String | Identifier of the organization group to which the user belongs. |
internalId | String | Identifier of the user in the information system of the organization. |
customFields | Map<String,Object> | Custom fields available specifically for this user, mapped by their key. |
vehicles | Vehicle[] | List of personal vehicles belonging to the user. These vehicles may be referenced in mileage expenses. |
preferredPaymentMethodId | String | Identifier of the preferred payment method of the user, to be selected by default in graphical interfaces. |
preferredCountry | String | Code of the preferred country of the user, to be selected by default in graphical interfaces. |
preferredCurrency | String | Code of the preferred currency of the user, to be selected by default in graphical interfaces. |
preferredDistanceUnit | DistanceUnit | Code of the preferred distance unit of the user. Allowed values are KM and MI, default is KM. |
preferredVehicleId | String | Identifier of the preferred vehicle of the user, to be selected by default in graphical interfaces. |
updatedAt | OffsetDateTime | Timestamp at which the user was last updated. |
createdAt | OffsetDateTime | Timestamp at which the user was created. |
blockedAt | OffsetDateTime | Timestamp at which the user was blocked. This field is null if the user is not blocked. |
profiles | UserProfile[] | List of profiles associated to the user, allowing him/her to work in the expense workflow. |
mainAccount | Boolean | Boolean indicating whether it is the user main/default account. Default is false, unless it is the only account. |
phone | String | The user phone number. |
delegations | Delegation[] | Delegations granted to the user, either on groups, or on other users. |
UserInvitation
Invitation for a user to join an organization. Once the invitation is accepted, the user invitation is used to create the user.
field | type | description |
---|---|---|
id | String | Unique identifier of the User invitation in Jenji (UUID). |
login | String | Login used by the user to authenticate to Jenji. |
String | Email address at which the user may be contacted, to receive technical notifications. | |
firstName | String | First name of the user, like "Alex" in "Alex Pence". |
lastName | String | Last name of the user, like "Pence" in "Alex Pence". |
organizationId | String | Identifier of the organization to which the user belongs. |
groupId | String | Identifier of the organization group to which the user belongs. |
internalId | String | Identifier of the user in the information system of the organization. |
customFields | Map<String,Object> | Custom fields available specifically for this user, mapped by their key. The definitions of custom fields are set on the root group. |
vehicles | Vehicle[] | List of personal vehicles belonging to the user. These vehicles may be referenced in mileage expenses. |
preferredPaymentMethodId | String | Identifier of the preferred payment method of the user, to be selected by default in graphical interfaces. |
preferredCountry | String | Code of the preferred country of the user, to be selected by default in graphical interfaces. |
preferredCurrency | String | Code of the preferred currency of the user, to be selected by default in graphical interfaces. |
state | String | State of the user invitation. The state can be "WAITING", "ACCEPTED" or "DELETED". |
inviteSentAt | OffsetDateTime | Timestamp at which the user invitation was sent. |
createdAt | OffsetDateTime | Timestamp at which the user invitation was created. |
deletedAt | OffsetDateTime | Timestamp at which the user invitation was deleted. This field is null if the user invitation is not deleted. |
profiles | UserProfile[] | List of profiles associated with the user, allowing him/her to work in the expense workflow. |
phone | String | The user phone number. |
delegations | Delegation[] | Delegations to be granted to the user, either on groups, or on other users. |
UserProfile
The management of expenses over time usually follows certain steps, for instance checking the compliance of an expense, accepting or rejecting an expense, and so on. These steps are articulated inside an expense Workflow , which may be either a standard Jenji workflow, or a custom workflow.
A Profile declares a role in that workflow (e.g. a "manager" in charge of accepting expenses), and is associated with rights to perform transitions in the workflow.
Organization users may be assigned profiles for certain organization groups, which allow them to process the expenses according to the workflow in use in the organization.
The profile named admin always exists and gives administrating rights in the organization or on any groups. This profile does not allow to perform any expense transition. Admins of the root group have access to all the organization configuration. Admins of sub-groups can only manage user related configuration for their allowed sub-groups and all sub-groups below.
The profile named accountant always exists and gives accounting rights in the organization or on any groups. This profile allows the creation and management of accounting and payroll exports. If combined with the admin profile, it also allows the edition of the accounting configuration.
field | type | description |
---|---|---|
profileId | String | Mandatory. The identifier of the profile used in the workflow. The organization user will assume this role / profile when processing an expense (e.g. accepting an expense as a manager). |
groupIds | String[] | Mandatory. The list of organization groups for which the user may assume the profile. |
Vehicle
A personal vehicle for an organization user. Vehicles are registered to create and estimate mileage expenses, when an organization user travels with his/her personal vehicle, for business.
field | type | description |
---|---|---|
id | String | Unique identifier of the vehicle in Jenji (UUID). |
type | VehicleType | Type of the vehicle, like a car or a motorcycle. Estimation policies for mileage expenses differ depending on the type. |
label | String | The label of the vehicle, to help the user select the right vehicle when creating an expense. |
taxHorsepower | int | Tax horsepower of the vehicle, used to estimate the expense. |
engineCapacity | Integer | The engine capacity in cubic centimeters (cc). |
energy | VehicleEnergy | The energy used in the vehicle (Petrol, Diesel, Electric, LPG). |
fixedMileageRate | BigDecimal | Fixed mileage reimbursement rate, set by the organization, which overrides official tariffs. |
fixedMileageRateDistanceUnit | DistanceUnit | Fixed mileage reimbursement rate distance unit (km or miles) |
mileageCalculatorId | String | The specific mileage calculator to use when computing mileage expenses for this vehicle. When missing, mileage expenses are computed with the default rules applicable for the organization. |
disabledAt | OffsetDateTime | Timestamp at which the vehicle has been disabled. It may not be used in expenses anymore, but remains in the system for history purposes. |
checked | boolean | Whether the registration document has been verified. |
customFields | Map<String,Object> | Custom fields available specifically for this vehicle, mapped by their key. |
VehicleEnergy
Energy for a vehicle. Can be used by some mileage calculators to estimate a mileage expense.
value | description |
---|---|
ELECTRIC | Full electric. Hybrid cars are treated as either petrol or diesel cars for advisory fuel rates. |
PETROL | |
DIESEL | |
LPG | Liquefied Petroleum Gas. |
VehicleType
value | description |
---|---|
CAR | |
MOTORCYCLE | |
MOPED | |
BIKE |
WarningRule
A warning rule defines the conditions on how it should be applied and the labels to be showed to the user.
A single rule can have multiple sub-labels represented as options. For example, you can have a rule to alert of a threshold, and multiple levels of this threshold :
- warning label= Threshold exceeded
- option 1: code=m30
, label=Meal over 30\u20ac
- option 2: code=m60
, label=Meal over 60\u20ac
- option 3: code=t50
, label=Taxi over 50\u20ac
field | type | description |
---|---|---|
id | String | Unique identifier |
type | WarningRuleType | Rule type, for now only EXTERNAL type can be managed by api |
labels | Map<String,String> | Warning main label |
options | WarningRuleOption[] | Warning rule options. |
disabled | Boolean | Disabled rule. |
externalRuleId | String | The external rule ID (optional) |
WarningRuleOption
field | type | description |
---|---|---|
code | String | Technical code for this option |
labels | Map<String,String> | Labels for the option |
isPreventingValidation | Boolean | Indicates whether this option should prevent the validation of the expense or not |
WarningRuleType
value | description |
---|---|
EXTERNAL | External rule managed by api (warning manually set on expenses by api instead of Jenji's warning system) |
Waypoint
A waypoint is a geographical place, identified either by an address or by coordinates. A travel starts from a waypoint, optionally visits other waypoints, and ends on a waypoint. A simple round-trip travel would start at waypoint A (e.g. an address in Paris), arrive at B (e.g. an address in Lyon), then return back to A.
field | type | description |
---|---|---|
address | String | The address of the way point. |
longitude | BigDecimal | The longitude of the waypoint, if known. |
latitude | BigDecimal | The latitude of the waypoint, if known. |