# Error Handling
Source: https://docs.onsi.com/api-reference/error-handling
Learn how to handle errors from the API.
# Error Structure
Our API returns a consistent error structure for all errors. The API always returns a JSON response with an array of `issues`, Onsi Issues always have a `code` and a `message`.
An exhaustive list can be found lower down.
```json theme={null}
{
"issues": [
{
"code": "HeaderValidation",
"message": "Required",
"path": "x-api-key"
},
{
"code": "BodyValidation",
"message": "Required",
"path": "currency"
}
]
}
```
Using the `message` field to conditionally handle errors is not recommended as the `message` field may change in the
future. Always use the `code` field to conditionally handle errors, or any other property in a specific error, like
the `row` in an `InvalidContent` error.
# Error List
### Generic
We may introduce more specific error codes to replace the existing generic ones in the future. For now, we recommend
treating any generic error codes as a catch-all.
#### InternalServerError
This is our generic internal server error, this will be returned in cases where an unexpected error occurs
#### BadRequest
This is our generic bad request error, this will be returned in cases where the request is malformed or invalid and there is no more specific error code to return
A human-readable message used for debugging and logging
**Example:**
```json theme={null}
{
"code": "BadRequest",
"message": "The address provided must be based in the United Kingdom"
}
```
#### Forbidden
This is our generic forbidden error, this will be returned in cases where the user is not allowed to perform the requested action
A human-readable message used for debugging and logging
**Example:**
```json theme={null}
{
"code": "Forbidden",
"message": "You are not allowed to perform this action"
}
```
#### NotFound
This is our generic not found error, this will be returned in cases where the requested resource does not exist
A human-readable message used for debugging and logging
#### Conflict
This is our generic conflict error, this will be returned in cases where the request conflicts with the current state of the server
A human-readable message used for debugging and logging
#### RateLimitExceeded
The request was rate limited
A human-readable message used for debugging and logging
#### UnprocessableEntity
This is our generic unprocessable entity error, this will be returned in cases where the request is valid but cannot be processed due to business logic or other constraints
A human-readable message used for debugging and logging
### Request Validation
#### BodyValidation
An error occurred while validating the request body
A human-readable message used for debugging and logging
#### QueryValidation
An error occurred while validating the request query parameters
A human-readable message used for debugging and logging
#### PathValidation
An error occurred while validating the request path parameters
A human-readable message used for debugging and logging
#### HeaderValidation
An error occurred while validating the request headers
A human-readable message used for debugging and logging
### Specific
#### MemberNotFound
The member could not be found
A human-readable message used for debugging and logging
The unique identifier for a Member, prefixed with mem\_
**Example:**
```json theme={null}
{
"code": "MemberNotFound",
"message": "The member could not be found",
"memberId": "mem_foo"
}
```
#### MemberNotEligible
The member is not eligible to perform the requested action
A human-readable message used for debugging and logging
The unique identifier for a Member, prefixed with mem\_
#### MemberAlreadyInvited
The member has already been invited
A human-readable message used for debugging and logging
The ID of the member who already exists in the system
#### MemberInsufficientFunds
The member does not have enough funds to perform the requested action
A human-readable message used for debugging and logging
The unique identifier for a Member, prefixed with mem\_
#### BankAccountInvalid
The bank account provided is invalid
A human-readable message used for debugging and logging
#### FileContent
An error occurred while processing the file content, commonly used for CSV/Ecxel files
A human-readable message used for debugging and logging
The row number in the file where the error occurred
#### AmountBelowLowerLimit
The requested withdrawal intent amount is below the minimum which can be withdrawn, also returns the minimum amount which can be withdrawn
A human-readable message used for debugging and logging
A monetary value with currency. See [Money](/docs/schemas/money)
Price in lowest denomination of currency (e.g. cents)
ISO 4217 currency code
**Example:**
```json theme={null}
{
"code": "AmountBelowLowerLimit",
"message": "Withdrawal amount is below the lower limit of £10.00",
"lowerLimit": {
"amount": 1000,
"currency": "GBP"
}
}
```
#### AmountAboveUpperLimit
The requested withdrawal intent amount is above the maximum which can be withdrawn, also returns the maximum amount which can be withdrawn
A human-readable message used for debugging and logging
A monetary value with currency. See [Money](/docs/schemas/money)
Price in lowest denomination of currency (e.g. cents)
ISO 4217 currency code
**Example:**
```json theme={null}
{
"code": "AmountAboveUpperLimit",
"message": "Withdrawal amount is above the upper limit of £200.00",
"upperLimit": {
"amount": 20000,
"currency": "GBP"
}
}
```
#### InvalidAddMemberPayload
The payload provided to add a member is invalid
A human-readable message used for debugging and logging
The email provided to add a member
#### InvalidUpdateMemberPayload
The payload provided to update a member is invalid
A human-readable message used for debugging and logging
The unique identifier for a Member, prefixed with mem\_
#### InvalidRemoveMemberPayload
The payload provided to remove a member is invalid
A human-readable message used for debugging and logging
The unique identifier for a Member, prefixed with mem\_
# Idempotency
Source: https://docs.onsi.com/api-reference/idempotency
Learn how to make idempotent requests to the Onsi API.
# Idempotency in the Onsi API
When integrating with the Onsi API, ensuring that your requests are idempotent is crucial for maintaining data integrity and consistency, especially in environments susceptible to network issues or when dealing with operations that should not be duplicated. Idempotency ensures that multiple identical requests will have the same effect as making a single request.
## Understanding Idempotency
An idempotent API operation can be called many times without different outcomes, no matter how many requests are made. This is particularly important for POST, PUT, and DELETE requests which modify data.
## Implementing Idempotency with `x-idempotency-key`
The Onsi API supports idempotency for safe and unsafe HTTP methods through the use of the `x-idempotency-key` header. Clients should generate and attach this key to requests that need to be idempotent. Here’s how it works:
* **Key Generation**: The client generates a unique key for each operation. This key is typically a UUID, but it can be any string you desire.
* **Key Usage**: The client includes this key in the HTTP header `x-idempotency-key` when making a request.
* **Server Processing**: On the server side, the API checks if a request with the same idempotency key has been processed before:
* If yes, and the previous request was successful (returned a 2XX status code), the server will not reprocess the request but will return the result of the previous request.
* If no previous request with that key exists, the server processes the request as normal.
Idempotency keys will be respected for 7 days after the initial request. After this time, the key will be considered
expired and the request will be processed as normal.
### Benefits of Using `x-idempotency-key`
1. **Avoid Duplicate Processing**: Protects against creating duplicate resources or performing the same operation twice.
2. **Reliability**: Enhances the reliability of the API by ensuring that retries due to network failures or other issues do not result in unintended effects.
3. **Consistency**: Ensures data consistency, especially in distributed systems where multiple requests might overlap.
### Example: Creating a Member with `POST /v1/members`
Below is a simple example of how to use the `x-idempotency-key` when creating a new member via the `/v1/members` endpoint.
#### Request:
```bash theme={null}
curl -X POST https://api.onsi.com/v1/members \
-H "Content-Type: application/json" \
-H "x-idempotency-key: 83e41c7e-f7b5-4e06-be92-2a8f2f3b4c68" \
-d '{
"firstName": "John",
"lastName": "Smith",
"email": "john.doe@example.com"
...
}'
```
#### Response:
```json theme={null}
{
"email": "jsmith@example.com",
"memberId": "mem_q5sdae3se6eg9m9dcvug",
"firstName": "John",
"lastName": "Smith",
"phone": "+447123456789",
"tier": "Gold",
"workerId": "ID_123",
"status": "active"
}
```
In this example, if the request is accidentally sent twice with the same `x-idempotency-key`, the Onsi API will recognize that the operation has already been performed and will not create a duplicate member. Instead, it will return the details of the member created by the first request.
## Conclusion
Using the `x-idempotency-key` in your requests to the Onsi API is a best practice that should be adopted to ensure the robustness and reliability of your application. By implementing idempotent operations, you safeguard your API interactions against unintended duplications and provide a more stable and consistent user experience.
# Introduction
Source: https://docs.onsi.com/api-reference/introduction
Learn how to interact with the Onsi API
# Introduction to the Onsi API
The Onsi API provides a comprehensive set of endpoints for seamless interaction with the Onsi platform. With this API, you can easily search for members, send invitations, and update member details.
* Production Base URL: [https://api.onsi.com](https://api.onsi.com)
* Sandbox Base URL: [https://api.onsi.dev](https://api.onsi.dev)
## Authentication
To protect the privacy and security of our data, the Onsi API requires authentication for all requests. Include your API key in the x-api-key header to authenticate your requests.
To request an API key, please reach out to us.
Example:
```json theme={null}
{
"x-api-key": "your_api_key_here"
}
```
## Response Codes
The Onsi API uses standard HTTP response codes to indicate the success or failure of an API request, see below to go to our Guide on Error handling.
Read our in-depth guide on the errors returned by the Onsi API and how to handle them.
## Data Format
All request and response bodies in the Onsi API are in JSON format. Make sure to include a Content-Type: application/json header in your requests and ensure that your JSON bodies are properly formatted.
With this information, you're
ready to start exploring the full potential of the Onsi API. Enjoy building your integration!
# Create Batch Job
Source: https://docs.onsi.com/api-reference/jobs/batch-job
POST /v1/members/jobs
Creates a new job, which runs asynchronously and returns a job ID. The job ID can be used to check the status of the job.
The job contains an array of operations, of the same format as the single changes APIs:
* **Add** - Invites a new member to your Onsi programme.
* **Replace** - Replaces the member's data with new information. An inactive member **will be** re-added to Onsi.
* **Update** - Updates the member's data with new information. Does **not** re-add inactive members.
* **Remove** - Removes the member from your Onsi programme.
#### Unsetting Bank Details
For **Replace** and **Update** operations, you can remove a member's bank details by setting `accountDetails` to `null`.
#### Relevant Error Codes
If there are issues with any of the operations, the API will return a `400` status code with the following error codes:
If there are issues, Onsi will not process any of the operations in your request, and will not create a job. You will
need to fix the issues and send a subsequent request.
* [InvalidAddMemberPayload](/api-reference/error-handling#invalidaddmemberpayload)
* [InvalidUpdateMemberPayload](/api-reference/error-handling#invalidupdatememberpayload)
* [InvalidRemoveMemberPayload](/api-reference/error-handling#invalidremovememberpayload)
# Upload Full Member List CSV
Source: https://docs.onsi.com/api-reference/jobs/csv
PUT /v1/members/jobs/csv
Upload a CSV file containing your entire target member list. The file should contain the following columns:
* `email`: The email address of the member.
* `first_name`: The first name of the member.
* `last_name`: The last name of the member.
* `phone`: (allowed empty) The phone number of the member.
* `tier`: The tier of the member.
* `worker_id` (optional, allowed empty): The worker ID of the member.
The API doesn't care about the casing of the columns, e.g. "Worker ID" is acceptable
#### Relevant Error Codes
When parsing the file uploaded we can return:
* [FileContent](/api-reference/error-handling#filecontent) if the file has validation issues.
# Upload Full Member List CSV V2
Source: https://docs.onsi.com/api-reference/jobs/csv-v2
PUT /v2/members/jobs/csv
Upload a CSV file containing your entire target member list. This endpoint behaves identically to
[V1](/api-reference/jobs/csv), with one key difference: when bank detail columns are present but
empty for an existing member that has bank details on their profile, their bank details will be
**unset** (disabled). In V1, empty bank detail columns are ignored and existing bank details are
preserved.
The file should contain the following columns:
* `email`: The email address of the member.
* `first_name`: The first name of the member.
* `last_name`: The last name of the member.
* `phone`: (allowed empty) The phone number of the member.
* `tier`: The tier of the member.
* `worker_id` (optional, allowed empty): The worker ID of the member.
* Bank detail columns (optional, allowed empty). **In V2, leaving these empty will unset existing bank details.**
* For **UK** partners:
* `sort_code`: The sort code of the member's bank account.
* `account_number`: The account number of the member's bank account.
* `account_holder`: The name of the account holder.
* For **EU** partners:
* `iban`: The IBAN of the member's bank account.
* `account_holder`: The name of the account holder.
The API doesn't care about the casing of the columns, e.g. "Worker ID" is acceptable
#### Bank Details Handling
| Scenario | V1 Behaviour | V2 Behaviour |
| ------------------------------------------------------------------ | ----------------------------------- | ----------------------------------- |
| Bank detail columns empty for existing member with bank details | Existing bank details **preserved** | Existing bank details **removed** |
| Bank detail columns empty for existing member with no bank details | Member remains with no bank details | Member remains with no bank details |
| Bank detail columns populated | Bank details updated | Bank details updated |
| New member with bank details | Bank details set | Bank details set |
#### Relevant Error Codes
When parsing the file uploaded we can return:
* [FileContent](/api-reference/error-handling#filecontent) if the file has validation issues.
# Get Job
Source: https://docs.onsi.com/api-reference/jobs/get-job
GET /v1/members/jobs/{jobId}
Returns a job by its ID, useful to check the status of a job.
# Remove Member
Source: https://docs.onsi.com/api-reference/members/delete
DELETE /v1/members/{id}
Removes the member from your programme however, the member will still have access to the ONSI app.
#### Relevant Error Codes
If there are any issues with the delete, the API will return a `400` status code with the following error codes:
* [InvalidRemoveMemberPayload](/api-reference/error-handling#invalidremovememberpayload)
# Get Member
Source: https://docs.onsi.com/api-reference/members/get
GET /v1/members/{id}
This API returns a single member given their Onsi provided `member_id`.
# Get Tiers
Source: https://docs.onsi.com/api-reference/members/get-tiers
GET /v1/tiers
Returns all tiers available for your programme, these are pre-setup for you, please speak to your Onsi contact.
# Update Member
Source: https://docs.onsi.com/api-reference/members/patch
PATCH /v1/members/{id}
Updates an existing member, identified by their `memberId`.
#### Unsetting Bank Details
To remove a member's bank details, set `accountDetails` to `null`.
#### Relevant Error Codes
If there are any issues with the update, the API will return a `400` status code with the following error codes:
* [InvalidUpdateMemberPayload](/api-reference/error-handling#invalidupdatememberpayload)
# Invite Member
Source: https://docs.onsi.com/api-reference/members/post
POST /v1/members
This invites a new member to your platform, when they are created they will have the status of `invited`, if their email already has an associated Onsi account their status will go straight to `active`.
#### Relevant Error Codes
If there are any issues with the member add, the API will return a `400` status code with the following error codes:
* [MemberAlreadyInvited](/api-reference/error-handling#memberalreadyinvited) a member with this email is currently active or invited.
* [InvalidAddMemberPayload](/api-reference/error-handling#invalidaddmemberpayload) for any other add member payload issues.
# Replace Member
Source: https://docs.onsi.com/api-reference/members/put
PUT /v1/members/{id}
Replacing an existing member, identified by their `memberId`.
As you're providing the entire desired member state, members with a status of `inactive` will be **re-activated** on your Onsi programme.
#### Unsetting Bank Details
To remove a member's bank details, set `accountDetails` to `null`.
#### Relevant Error Codes
If there are any issues with the member replace, the API will return a `400` status code with the following error codes:
* [InvalidUpdateMemberPayload](/api-reference/error-handling#invalidupdatememberpayload)
# Search Members
Source: https://docs.onsi.com/api-reference/members/search
GET /v1/members
This API can be used to search for members on your platform.
## Member Statuses
* `active`: Member has accepted the invitation and is active on the platform.
* `invited`: Member has been invited but has not yet accepted the invitation.
* `inactive`: Member has been removed from the platform, or they have requested their Onsi account to be deleted.
## Member Identifiers
* `memberId`: The Onsi-issued unique identifier for the member.
* `workerId`: An external identifier for the member, such as an employee ID, this is typically used to identify the member in your system (this is optional).
# Complete Withdrawal
Source: https://docs.onsi.com/api-reference/pay/complete-withdrawal
POST /v1/pay/withdrawals/complete
At this point you should've presented the withdrawal intent to the user, once they've confirmed the amount, fees, and destination bank account, you can proceed to complete the withdrawal.
Once this request is complete the fund transfer will be initiated to the destination bank account, and any applicable fees will be deducted from the user's balance.
**Testing Considerations**: Please avoid running automated tests against this endpoint as test accounts require manual
replenishment.
#### Relevant Error Codes
The endpoint-specific error codes to pay attention to are:
* [MemberInsufficientFunds](/api-reference/error-handling#memberinsufficientfunds)
* [BankAccountInvalid](/api-reference/error-handling/#bankaccountinvalid)
* [AmountBelowLowerLimit](/api-reference/error-handling/#amountbelowlowerlimit)
* [AmountAboveUpperLimit](/api-reference/error-handling/#amountaboveupperlimit).
In rare cases, you may receive a [Unprocessable Entity Error](snippets/generated-errors#UnprocessableEntity) which indicates that On Demand Pay is temporarily unavailable.
# Create Withdrawal Intent
Source: https://docs.onsi.com/api-reference/pay/create-withdrawal-intent
POST /v1/pay/withdrawals/intent
Create a withdrawal intent given an intended withdrawal amount, and the member who will receive the funds.
We will process the request, calculate the fee (dependant on the member's tier) and return:
* `netAmount` - a [Money object](/docs/schemas/money) representing the amount that will be transferred to the member
* `fee` - a [Money object](/docs/schemas/money) representing the fee that will be charged
* `accountDetails` - An object containing the bank account details the `netAmount` will be transferred to
Please see the [On Demand Pay](/docs/pay/embedded-pay) documentation for more information on the lifecycle of a withdrawal intent.
#### Relevant Error Codes
The endpoint-specific error codes to pay attention to are:
* [MemberInsufficientFunds](/api-reference/error-handling#memberinsufficientfunds)
* [BankAccountInvalid](/api-reference/error-handling/#bankaccountinvalid)
* [AmountBelowLowerLimit](/api-reference/error-handling/#amountbelowlowerlimit)
* [AmountAboveUpperLimit](/api-reference/error-handling/#amountaboveupperlimit).
In rare cases, you may receive a [Unprocessable Entity Error](snippets/generated-errors#UnprocessableEntity) which indicates that On Demand Pay is temporarily unavailable.
# Get Cycle
Source: https://docs.onsi.com/api-reference/pay/get-cycle
GET /v1/pay/cycles/{id}
This endpoint returns a single pay cycle, by its ID.
* `Closed` - The cycle is closed, no moe withdrawals can be made, and you can now perform your final deductions/accounting.
* `Open` - The cycle is open, members can still make withdrawals.
# Get Cycle Deductions
Source: https://docs.onsi.com/api-reference/pay/get-cycle-deductions
GET /v1/pay/cycles/{id}/deductions
This endpoint returns a list of all members who have withdrawn during this pay cycle. Members who have not withdrawn will not be included in the response.
For each member we provide a total of the deductions made during this pay cycle.
For example:
* Bob makes 2 £100 withdrawals during the pay cycle.
* Jane made no withdrawals during the pay cycle.
```json theme={null}
{
"deductions": [
{
"memberId": "mem_bob",
"total": {
"amount": 20000,
"currency": "GBP"
}
}
]
}
// members with no withdrawals will not be included in the response
```
We have written a guide for [end of cycle processing](/docs/pay/end-of-cycle) for your pay cycle, which will walk through the recommended sequencing of calls to this endpoint.
Ensure that you have checked the pay cycle is `Closed` before processing any payroll deductions using this endpoint -
Otherwise withdrawals may still be made.
# Get Cycles
Source: https://docs.onsi.com/api-reference/pay/get-cycles
GET /v1/pay/cycles
Search pay cycles, returns the latest pay cycle first
This endpoint returns a list of all pay cycles, past and present.
* `Closed` - The cycle is closed, no moe withdrawals can be made, and you can now perform your final deductions/accounting.
* `Open` - The cycle is open, members can still make withdrawals.
## Ordering and Contiguity
Pay cycles are designed to be perfectly contiguous, meaning they always touch each other with zero gaps between them. For example:
* `2025-06-30` → `2025-07-06` (Open)
* `2025-06-23` → `2025-06-29` (Closed)
* `2025-06-16` → `2025-06-22` (Closed)
The cycles returned are ordered with the most recent cycle first, so the top result will always be the latest cycle and should always be `Open`.
# Get Member Balance
Source: https://docs.onsi.com/api-reference/pay/get-member-balance
GET /v1/pay/members/{memberId}/balance
Returns the balance of a member, and any withdrawal limits that apply to the member.
## Current Balance
The `available` field represents the actual balance a member currently has for withdrawal.
## Withdrawal Limits
The `lowerLimit` and `upperLimit` fields define the range of amounts that a member is allowed to withdraw:
* **Lower Limit (`lowerLimit`)**: The minimum amount a member can withdraw.
* **Upper Limit (`upperLimit`)**: The maximum amount a member can withdraw.
These limits do not directly factor into the balance but instead serve to restrict the amount a member can withdraw in
a single transaction.
### Computation of Withdrawable Amount
Given the available balance and the limits, the withdrawable amount can be
computed as follows:
* **Minimum Withdrawable Amount**: Is always the `lowerLimit`, as if the balance is less than the lower limit they cannot withdraw.
* **Maximum Withdrawable Amount**: This is the smaller value between the available balance and the upper limit.
```text theme={null}
Maximum Withdrawable Amount = min(available, upperLimit)
```
## Temporarily Unavailable
In rare cases, On Demand Pay may be temporarily unavailable. To show this, we return `temporarilyUnavailable: true` in the balance response.
If this happens, withdrawals will be temporarily unavailable and any calls to create withdrawal intent or complete withdrawal endpoints will be rejected.
# Get Member Withdrawals
Source: https://docs.onsi.com/api-reference/pay/get-member-withdrawals
GET /v1/pay/members/{memberId}/withdrawals
Returns a list of the pay withdrawals for a given member, pagination is supported.
This endpoint is deprecated in favour of [GET /v1/pay/withdrawals](/api-reference/pay/get-withdrawals) and will be
removed in the next version of the API. The new endpoint also allows member-specific filtering, as well as more
complex querying.
# Get Withdrawals
Source: https://docs.onsi.com/api-reference/pay/get-withdrawals
GET /v1/pay/withdrawals
Search through all withdrawals across your entire member base, you can filter by member, by cycle or by date range.
### Filtering
* **Member ID (`memberId`)**: Filter withdrawals by a specific member's internal Onsi ID.
* **Pay Cycle ID (`payCycleId`)**: Filter withdrawals by a specific pay cycle ID.
* **From Date (`fromDate`)**: Start the results after this date (ISO 8601 datetime format).
* **To Date (`toDate`)**: End the results before this date (ISO 8601 datetime format).
### Pagination
We return a `hasMore` flag to indicate if there are more results to fetch, we do not return a `total` for this resource.
* **Has More (`hasMore`)**: Whether there are more results to fetch.
# Create Pay Run
Source: https://docs.onsi.com/api-reference/pay/upload-pay
POST /v1/pay/run
Create a pay run to make pay available to your members.
Include a list of Member IDs, and the amount you would like to make available in the form of a `Money` object (please see [Money Object](/docs/schemas/money)).
We will either respond with a list of issues, or with a created `PayRun` object.
The `PayRun` will, by default, be executed after a 10 minute grace period. This can be seen in the `scheduledFor` field of the `PayRun` object.
We strongly reccomend using an `x-idempotency-key` to avoid duplicate pay run uploads, and therefore duplicate money
being made available to your members.
# Rate Limits
Source: https://docs.onsi.com/api-reference/rate-limits
Learn about what rate limits are and how to handle them.
## Scalability & Throttling
The platform scales with load and enforces throttling at **100 requests per second per client**. We allow short bursts above the limit within reasonable bounds to accommodate natural traffic patterns.
## Rate Limit Responses
When rate limits are exceeded, the API will return a `429 Too Many Requests` status code along with a [`RateLimitExceeded`](/api-reference/error-handling#ratelimitexceeded) error response.
**Example response:**
```json theme={null}
{
"code": "RateLimitExceeded",
"message": "Request rate limit exceeded. Please reduce your request frequency."
}
```
## Best Practices
* Implement exponential backoff in your client applications
* Monitor your request rates to stay within limits
* Utilise batch endpoints where possible
# Changelog
Source: https://docs.onsi.com/docs/changelog
## Unsetting Bank Details 🏦
Partners can now remove a member's existing bank details via the API.
### APIs
* [Update Member](/api-reference/members/patch) - Set `accountDetails` to `null` to unset bank details
* [Replace Member](/api-reference/members/put) - Set `accountDetails` to `null` to unset bank details
* [Batch Job](/api-reference/jobs/batch-job) - Set `accountDetails` to `null` on **Replace** or **Update** operations to unset bank details
## CSV Upload V2 🆕
A new version of the CSV member upload endpoint is now available. It behaves identically to V1 with one key change: when bank detail columns are present but empty for a member that already has bank details on their profile, those bank details will be **removed**. In V1, empty bank detail columns are ignored and existing bank details are preserved.
### APIs
* [Upload Full Member List CSV V2](/api-reference/jobs/csv-v2) - `PUT /v2/members/jobs/csv`
## Pay Cycle APIs 🆕
Due to popular demand, we've introduced APIs to view Pay Cycles and their deductions via the Onsi API.
### APIs
* [Get Pay Cycles](/api-reference/pay/get-cycles)
* [Get Pay Cycle](/api-reference/pay/get-cycle)
* [Get Pay Cycle Deductions](/api-reference/pay/get-cycle-deductions)
The documentation for the recommended processing of Pay Cycle deductions can be found [here](/docs/pay/end-of-cycle).
## Member Replace API 🆕
Introduced the ability to replace member data entirely, simplifying member updates for partners.
### APIs
* [Replace Member](/api-reference/members/put) - PUT endpoint for complete member replacement
### Benefits
This new endpoint allows for easier program updates, as you don't need to compare the current member state to the desired state to decide what changes to make.
Simply provide the entire desired member state.
## Idempotency Support 🔄
Added comprehensive idempotency support to ensure reliable API operations and prevent duplicate processing.
### Features
* [Idempotency documentation](/api-reference/idempotency) with implementation guidance
* Support for `x-idempotency-key` header across all mutation endpoints
* 7-day key retention for reliable retry handling
## API Launch 🎉
We're excited to announce the launch of the Onsi API! This initial release provides the foundation for partners to integrate with Onsi's platform programmatically.
# Get Started
Source: https://docs.onsi.com/docs/member-management/get-started
Everything you need to know about managing your members via the Onsi Member API. Below you'll find documentation on how to create and update your members without the need for manual administration via the Onsi Platform.
# Member Lifecycle
* `active`: Member has accepted the invitation and is active on the platform.
* `invited`: Member has been invited but has not yet accepted the invitation.
* `inactive`: Member has been removed (or offboarded) from the platform.
# Categories of Member Management
## 1. [Full Member List CSV](/api-reference/jobs/csv):
The full member list CSV allows you to inform of us your **complete** member list, this allows us to calculate the differences and action that.
For instance, if you have 100 members in your existing member list, and you upload a new CSV with 50 members, we will update any members who have changed, and offboard the 50 members who are no longer in the list.
This is identical to the CSV uploaded through the Onsi Platform for batch member management
## 2. Single Member Actions
This is our most reactive method of managing members, you can create, read, update and delete members in real-time - we will action changes immediately and return the result straight away.
* [Create](/api-reference/members/post): Invite a new member to your platform by providing their details.
* [Read](/api-reference/members/get): Retrieve information about a specific member using their unique identifier.
* [Update](/api-reference/members/patch): Modify attributes of a member, such as updating their Tier, changing their name, or updating other relevant information.
* [Replace](/api-reference/members/put): Replace attributes of a member. Inactive members will be re-invited on to the platform.
* [Delete](/api-reference/members/delete): Offboard a member from the platform, effectively removing them from your member list.
## 3. [Batch Member Actions](/api-reference/jobs/batch-job)
This is the batch version of the single member actions, you can perform multiple actions on multiple members at once, this is useful for executing large changes to your member list.
For example, this is the ideal method for updating the Tier of 100 members at once, or offboarding 50 members in one go.
## Recommended approach
Our recommended approach for updating your programme is to use the [Create Batch Job API](/api-reference/jobs/batch-job). This API allows you to send an array of actions to be performed on your members. While it requires you to calculate which actions to take on your end, it offers greater control and ensures that updates align precisely with your system's logic. Additionally, this API allows you to batch multiple actions into a single request, making it efficient for synchronising your programme at specific intervals.
If you prefer to target individual members, you can use the [single-member APIs](/api-reference/members). These APIs allow you to update, invite, or remove specific members by their Member ID, giving you full control over changes on a case-by-case basis.
Alternatively, you can use the [Upload Full Member List CSV API](/api-reference/jobs/csv). This API takes a CSV of your current member list and performs all the necessary calculations automatically, determining whether a member needs to be invited, re-invited, updated, or removed. However, this approach is more destructive because it replaces the current state of your programme and may cause unintended side effects if the CSV does not accurately reflect your desired member state.
# Member Tiers
Members each have exactly one associated "Tier", which represents their status or level within the platform. Tiers can be used to differentiate between different cohorts of members, each tier may have different offerings within the Onsi platform.
Tiers can be changed at any time via the [update member](/api-reference/members/patch) endpoint or the [replace member](/api-reference/members/put) endpoint, and the tier change will take effect immediately.
# Member Action Jobs
When you perform a bulk action, you will receive back a `jobId`, this ID can be used to query the status of the job to see if it has completed, please see the [get job](/api-reference/jobs/get-job) endpoint for more information.
# Embedded Pay
Source: https://docs.onsi.com/docs/pay/embedded-pay
Everything you need to know about how to seamlessly manage your Pay programme with the Onsi On-demand Pay API. Below you'll find documentation on how to integrate Pay into your application.
# Introduction
Embedded pay allows you to embed the Onsi pay experience into your application, allowing you to perform withdrawals on behalf of your members.
Embedded pay is an additional feature that can be enabled on your account. Please contact us to enable this feature.
## Withdrawal Journey
The withdrawal process for a member is as follows:
Show a member their available balance from the [Get Member Balance](/api-reference/pay/get-member-balance) endpoint,
present them the option to input the amount they would like to withdraw.
Create a withdrawal intent using the [Create Withdrawal Intent](/api-reference/pay/create-withdrawal-intent)
endpoint, this returns any associated fees which will be deducted (if applicable), make sure to present this
information to the user so they may confirm.
If the member confirms the withdrawal, call the [Confirm Withdrawal](/api-reference/pay/complete-withdrawal)
endpoint to complete the withdrawal.
After the withdrawal is confirmed, the member will receive the net amount of the withdrawal, and the fees will be deducted from the member's account.
## Pay Management
Your pay programme can be managed through the Onsi API.
Pay cycles will be created for your by Onsi during your onboarding process. From then on all you need to do is let us know who you would like to pay and how much, and we will take care of the rest.
When pay details are uploaded they will be associated with the current cycle that is open.
If a member is included in you pay upload that has yet to be invited by you to our platform they will not be included in the pay details, we will respond with a 400 and list the ineligible members.
To make a member eligible you will need to first invite them to the platform. Then you can upload their pay details and they will be included in the pay cycle.
# End of Cycle Processing
Source: https://docs.onsi.com/docs/pay/end-of-cycle
Learn how to efficiently process end of cycle deductions and integrate them with your payroll system using the Onsi API.
## Recommended Strategy
Our recommended approach for end of cycle deduction processing follows a simple polling pattern that ensures you never miss a cycle and can easily integrate with any payroll system.
Configure your system to poll the [Get Cycles](/api-reference/pay/get-cycles) endpoint on a regular cadence (daily
is recommended, but you can adjust based on your needs).
From the cycles response, find the most recent cycle with status `Closed`. This indicates that no more withdrawals
can be made and the cycle is ready for final accounting.
It's worth noting that only when a Pay Cycle is `Closed` are members no longer able to make withdrawals. Don't
process your payroll until the cycle is `Closed`.
Use the [Get Cycle Deductions](/api-reference/pay/get-cycle-deductions) endpoint to get a complete list of all
members and their total deduction amounts for the cycle.
Paginate through all deduction results to ensure you capture every member's deductions. The endpoint supports
pagination with `skip` and `take` parameters.
Feed the deduction data into your payroll system using your preferred method - API integration, CSV upload, or
automation tools.
# Member
Source: https://docs.onsi.com/docs/schemas/member
A member is the core entity in the Onsi platform, they are the end users who you invite to the platform.
You should manage members via the [Member Management API](/docs/member-management/get-started)
# Money
Source: https://docs.onsi.com/docs/schemas/money
Monetary values are encoded combining the currency and amount, using the smallest unit of currency to ensure accuracy and prevent floating-point issues.
### MoneySchema Definition
The `MoneySchema` includes:
* **amount**: Integer representing the value in the smallest currency unit (e.g., pence for GBP).
* **currency**: ISO 4217 currency code indicating the currency type.
```json theme={null}
{
"exampleMoney": {
"amount": 1050,
"currency": "GBP"
}
}
```
## Supported Currencies
Supports any currency with an ISO 4217 code.
## Base Units for Currency
Transactions use the smallest currency unit to avoid rounding errors, e.g., 1050 in GBP represents £10.50.
# Pay cycle
Source: https://docs.onsi.com/docs/schemas/pay-cycle
Pay cycles can be retrieved via the [Get Cycles](/api-reference/pay/get-cycles) and the [Get Cycle](/api-reference/pay/get-cycle) endpoints.
# Pay run
Source: https://docs.onsi.com/docs/schemas/pay-run
Pay runs can be uploaded via the [Upload Pay](/api-reference/pay/upload-pay) endpoint.
# Tier
Source: https://docs.onsi.com/docs/schemas/tier
Tiers can be retrieved via the [Get Tiers](/api-reference/members/get-tiers) endpoint.
# Withdrawal
Source: https://docs.onsi.com/docs/schemas/withdrawal
Withdrawals can be retrieved via the [Get Withdrawals](/api-reference/pay/get-withdrawals) endpoint,
if you are using Embedded Pay you can create a withdrawal on behalf of a member via the [Create Withdrawal Intent](/api-reference/pay/create-withdrawal-intent) endpoint.