Query structured spec data via REST or MCP. Get exactly what your agent needs.
https://api.oysterhr.com
/oauth2/token
Oyster grants access to API resources based on OAuth. This means that individual customers grant API access to Developer Apps that you create. This applies to both customers and partners. Follow these simple steps: <br><br> 1. [Create an Oyster account](https://app.oysterhr.com/sign_up) or [log in](https://app.oysterhr.com/users/sign_in) to your existing account. <br> <br> 2. Create an Oyster Developer App in the [Developer Tab](https://app.oysterhr.com/developer) (If you can't see the developer tab please contact us to enable it for your account). <br> Hint: If you are a customer doing this as a one time action you don't need to specify a functioning URL as step 3 will explain. <br> <br> 3. If you are a customer you can simply click on the "Authorization URL" and grant access to your own app. You will be redirected to the URL you specified when creating the Developer App. In the URL you will see that `?code=xxx` has been added to the URL. This is the `code` you need to create an access token. <br> If you are a partner add "Authorization URL to your application. The redirect_url should be a URL that goes back to your app and you're able to programmatically retrieve the URL query param of `?code=xxx` to then create an access token. <br> <br> 4. You need to first request an `authorization_code` with the API request detailed below. This will provide an `access_token` that is used as the Bearer Token for making API requests to Oyster. Ensure that you store the `refresh_token` for making future API requests. <br> <br> 5. If your `access_token` has expired then request a new one using your `refresh_token` that you have stored earlier. Ensure you store the new `refresh_token` each time as the previous ones will expire.
{
"content": {
"application/x-www-form-urlencoded": {
"schema": {
"$ref": "#/components/schemas/AuthenticationCreateAccessTokenRequest"
}
}
},
"required": true
}
POST /oauth2/token
/v1/company
Returns details about the connected company
GET /v1/company
/v1/departments
Returns a list of departments
| Name | In | Required | Type | Description |
|---|---|---|---|---|
| per_page | query | optional | integer | |
| page | query | optional | integer |
GET /v1/departments
/v1/engagements
Returns a list of engagements
| Name | In | Required | Type | Description |
|---|---|---|---|---|
| per_page | query | optional | integer | |
| page | query | optional | integer |
GET /v1/engagements
/v1/engagements/{id}
Returns details for an engagement with a given engagement ID.
| Name | In | Required | Type | Description |
|---|---|---|---|---|
| id | path | required | string | Engagement ID |
GET /v1/engagements/{id}
/v1/expenses
Creates a new expense for an engagement. This is an asynchronous operation. Returns operationKey that can be used to retrieve the operation to know if it's successfully completed
{
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ExpensesCreateOperationKeyRequest"
},
"examples": {
"Successfully created async operation": {
"value": {
"name": "An expense",
"category": "HOME_OFFICE",
"incurredOn": "2022-10-15",
"receiptUrl": "https://www.example.com/receipts/test.pdf",
"description": "",
"engagementId": "Xse7pSwV",
"receiptAmount": {
"decimal": "1.23",
"currencyCode": "GBP"
}
},
"summary": "Successfully created async operation"
}
}
}
}
}
POST /v1/expenses
/v1/expenses/{id}
Returns details for an expense with a given expense ID.
| Name | In | Required | Type | Description |
|---|---|---|---|---|
| id | path | required | string | Expense ID |
GET /v1/expenses/{id}
/v1/expenses/{id}/approve
Approves an expense.
| Name | In | Required | Type | Description |
|---|---|---|---|---|
| id | path | required | string | Expense ID |
POST /v1/expenses/{id}/approve
/v1/expenses/{id}/decline
Declines an expense.
| Name | In | Required | Type | Description |
|---|---|---|---|---|
| id | path | required | string | Expense ID |
{
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ExpensesDeclineExpenseRequest"
},
"examples": {
"Successful": {
"value": {
"reason": "exceeds budget for this period"
},
"summary": "Successful"
}
}
}
}
}
POST /v1/expenses/{id}/decline
/v1/meta/operations/{operation_key}
Returns details for an operation with a given operation key.
| Name | In | Required | Type | Description |
|---|---|---|---|---|
| operation_key | path | required | string | Operation key |
GET /v1/meta/operations/{operation_key}
/v1/payroll
Returns a list of payrolls
| Name | In | Required | Type | Description |
|---|---|---|---|---|
| per_page | query | optional | integer | |
| page | query | optional | integer | |
| from | query | optional | string | |
| to | query | optional | string | |
| include_records | query | optional | boolean |
GET /v1/payroll
/v1/payroll/{id}
Returns details for a payroll with a given payroll ID.
| Name | In | Required | Type | Description |
|---|---|---|---|---|
| id | path | required | string | Payroll ID |
GET /v1/payroll/{id}
/v1/time_off/entitlements
Returns entitlements for each engagement of the company.
| Name | In | Required | Type | Description |
|---|---|---|---|---|
| per_page | query | optional | integer | |
| page | query | optional | integer |
GET /v1/time_off/entitlements
/v1/time_off/requests
Returns all Time Off Requests for a company.
| Name | In | Required | Type | Description |
|---|---|---|---|---|
| per_page | query | optional | integer | |
| page | query | optional | integer |
GET /v1/time_off/requests
/v1/time_off/requests/{id}
Returns details for a request.
| Name | In | Required | Type | Description |
|---|---|---|---|---|
| id | path | required | string | Time Off Request ID |
GET /v1/time_off/requests/{id}
/v1/time_off/requests/{id}/approve
Approves a time off request.
| Name | In | Required | Type | Description |
|---|---|---|---|---|
| id | path | required | string | Time Off Request ID |
POST /v1/time_off/requests/{id}/approve
/v1/time_off/requests/{id}/reject
Rejects a time off request.
| Name | In | Required | Type | Description |
|---|---|---|---|---|
| id | path | required | string | Time Off Request ID |
{
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TimeOffRejectRequestRequest"
},
"examples": {
"Successful": {
"value": {
"reason": "We need you!"
},
"summary": "Successful"
}
}
}
}
}
POST /v1/time_off/requests/{id}/reject
AuthenticationCreateAccessTokenRequest
{
"type": "object",
"properties": {
"code": {
"type": "string",
"example": "1234ABCD",
"description": "The code is required when requesting an `authorization_code`."
},
"client_id": {
"type": "string",
"example": "1234ABCD",
"description": "The client_id of your Developer App. This can be found by visting https://app.oysterhr.com/developer"
},
"grant_type": {
"type": "string",
"example": "authorization_code",
"description": "First you need to request an `authorization_code`. Afterwards you can request a `refresh_token`."
},
"redirect_uri": {
"type": "string",
"example": "https://example.com/inbound",
"description": "The redirect_uri is required when requesting an `authorization_code`."
},
"client_secret": {
"type": "string",
"example": "1234ABCD",
"description": "The secret of your Developer App."
},
"refresh_token": {
"type": "string",
"example": "https://example.com/inbound",
"description": "A `refresh_token` is required when requesting a `refresh_token`. A `refresh_token` will be provided when requesting an `authorization_code`"
}
}
}
CompanyDetailsRetrieveResponse
{
"type": "object",
"required": [
"data"
],
"properties": {
"data": {
"$ref": "#/components/schemas/company"
}
}
}
DepartmentsGetAllResponse
{
"type": "object",
"required": [
"data",
"meta"
],
"properties": {
"data": {
"$ref": "#/components/schemas/departments"
},
"meta": {
"$ref": "#/components/schemas/meta"
}
}
}
EngagementsGetAllResponse
{
"type": "object",
"required": [
"data",
"meta"
],
"properties": {
"data": {
"$ref": "#/components/schemas/engagements"
},
"meta": {
"$ref": "#/components/schemas/meta"
}
}
}
EngagementsGetByIdResponse
{
"type": "object",
"required": [
"data"
],
"properties": {
"data": {
"$ref": "#/components/schemas/engagement"
}
}
}
ExpensesCreateOperationKeyRequest
{
"type": "object",
"required": [
"engagementId",
"name",
"incurredOn",
"category",
"receiptUrl",
"receiptAmount"
],
"properties": {
"name": {
"type": "string",
"minLength": 1
},
"category": {
"type": "string",
"minLength": 1
},
"incurredOn": {
"type": "string",
"format": "date",
"minLength": 1
},
"receiptUrl": {
"type": "string",
"minLength": 1
},
"description": {
"type": "string"
},
"engagementId": {
"type": "string",
"minLength": 1
},
"receiptAmount": {
"type": "object",
"required": [
"decimal",
"currencyCode"
],
"properties": {
"decimal": {
"type": "string",
"minLength": 1
},
"currencyCode": {
"type": "string",
"minLength": 1
}
}
}
}
}
ExpensesDeclineExpenseRequest
{
"type": "object",
"properties": {
"reason": {
"type": "string"
}
}
}
ExpensesGetByIdResponse
{
"type": "object",
"required": [
"data"
],
"properties": {
"data": {
"$ref": "#/components/schemas/expense"
}
}
}
OperationsGetByOperationKeyResponse
{
"type": "object",
"required": [
"data"
],
"properties": {
"data": {
"$ref": "#/components/schemas/operation"
}
}
}
PayrollGetAllPayrollsResponse
{
"type": "object",
"required": [
"data",
"meta"
],
"properties": {
"data": {
"$ref": "#/components/schemas/payrolls"
},
"meta": {
"$ref": "#/components/schemas/meta"
}
}
}
PayrollGetByIdResponse
{
"type": "object",
"required": [
"data"
],
"properties": {
"data": {
"$ref": "#/components/schemas/payroll"
}
}
}
TimeOffGetAllRequestsResponse
{
"type": "object",
"required": [
"data",
"meta"
],
"properties": {
"data": {
"$ref": "#/components/schemas/timeOffRequests"
},
"meta": {
"$ref": "#/components/schemas/meta"
}
}
}
TimeOffGetEntitlementsResponse
{
"type": "object",
"required": [
"data",
"meta"
],
"properties": {
"data": {
"$ref": "#/components/schemas/timeOffEntitlements"
},
"meta": {
"$ref": "#/components/schemas/meta"
}
}
}
TimeOffGetRequestResponse
{
"type": "object",
"required": [
"data"
],
"properties": {
"data": {
"$ref": "#/components/schemas/timeOffRequest"
}
}
}
TimeOffRejectRequestRequest
{
"type": "object",
"required": [
"reason"
],
"properties": {
"reason": {
"type": "string"
}
}
}
Token
{
"type": "object",
"properties": {
"scope": {
"type": "string",
"example": "read"
},
"created_at": {
"type": "number",
"example": 167474949830
},
"expires_in": {
"type": "number",
"example": 7200
},
"token_type": {
"type": "string",
"example": "Bearer"
},
"access_token": {
"type": "string",
"example": "1234ABCD"
},
"refresh_token": {
"type": "string",
"example": "1234ABCD"
}
}
}
address
{
"type": "object",
"required": [
"addressId",
"addressLine1",
"postalCode"
],
"properties": {
"city": {
"type": "string",
"nullable": true
},
"region": {
"type": "string",
"nullable": true
},
"addressId": {
"type": "string"
},
"postalCode": {
"type": "string",
"nullable": true
},
"countryCode": {
"type": "string",
"nullable": true
},
"addressLine1": {
"type": "string",
"nullable": true
},
"addressLine2": {
"type": "string",
"nullable": true
}
}
}
amount
{
"type": "object",
"required": [
"decimal",
"currencyCode"
],
"properties": {
"decimal": {
"type": "string",
"pattern": "^\\d+([.]\\d+)?$"
},
"currencyCode": {
"type": "string",
"maxLength": 3,
"minLength": 3
}
}
}
asyncResponse
{
"type": "object",
"properties": {
"meta": {
"type": "object",
"properties": {
"operationKey": {
"type": "string"
}
}
}
}
}
company
{
"type": "object",
"required": [
"companyId",
"name",
"registrationNumber",
"addresses"
],
"properties": {
"name": {
"type": "string"
},
"addresses": {
"type": "object",
"properties": {
"billingAddress": {
"$ref": "#/components/schemas/address",
"type": "object",
"nullable": true
},
"corporateAddress": {
"$ref": "#/components/schemas/address",
"type": "object",
"nullable": true
}
}
},
"companyId": {
"type": "string"
},
"registrationNumber": {
"type": "string"
}
}
}
department
{
"type": "object",
"required": [
"departmentId",
"name",
"description",
"engagementsCount"
],
"properties": {
"name": {
"type": "string"
},
"description": {
"type": "string",
"nullable": true
},
"departmentId": {
"type": "string"
},
"engagementsCount": {
"type": "integer"
}
}
}
departments
{
"type": "array",
"items": {
"$ref": "#/components/schemas/department"
}
}
engagement
{
"type": "object",
"required": [
"engagementId",
"engagementType",
"personalDetails",
"startDate",
"countryCode",
"role"
],
"properties": {
"role": {
"type": "string"
},
"state": {
"type": "string"
},
"contract": {
"type": "object",
"nullable": true
},
"startDate": {
"type": "string",
"format": "date"
},
"department": {
"type": "object",
"nullable": true,
"properties": {
"name": {
"type": "string"
},
"description": {
"type": "string"
},
"departmentId": {
"type": "string"
}
}
},
"employment": {
"type": "object",
"nullable": true
},
"modifiedAt": {
"type": "string",
"format": "date-time"
},
"countryCode": {
"type": "string"
},
"engagementId": {
"type": "string"
},
"terminations": {
"type": "array",
"items": {
"type": "object",
"properties": {
"state": {
"type": "string"
},
"proposedDate": {
"type": "string",
"format": "date"
}
}
}
},
"engagementType": {
"enum": [
"EMPLOYMENT",
"CONTRACT"
],
"type": "string"
},
"personalDetails": {
"type": "object",
"required": [
"name",
"addresses"
],
"properties": {
"name": {
"type": "string",
"nullable": true
},
"addresses": {
"type": "object",
"properties": {
"livingAddress": {
"$ref": "#/components/schemas/address",
"type": "object",
"nullable": true
},
"mailingAddress": {
"$ref": "#/components/schemas/address",
"type": "object",
"nullable": true
}
}
},
"dateOfBirth": {
"type": "string",
"nullable": true
},
"citizenships": {
"type": "array",
"items": {
"type": "string",
"nullable": true
}
},
"phoneNumbers": {
"type": "object",
"properties": {
"default": {
"$ref": "#/components/schemas/phoneNumber",
"type": "object",
"nullable": true
},
"emergency": {
"$ref": "#/components/schemas/phoneNumber",
"type": "object",
"nullable": true
}
}
}
}
},
"benefitEnrollments": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"plan": {
"type": "object",
"properties": {
"provider": {
"type": "string"
},
"descriptiveName": {
"type": "string"
}
}
},
"state": {
"type": "string"
},
"benefitEnrollmentId": {
"type": "string"
}
}
}
}
}
}
engagements
{
"type": "array",
"items": {
"$ref": "#/components/schemas/engagement"
}
}
error
{
"type": "object",
"properties": {
"error": {
"type": "object",
"properties": {
"message": {
"type": "string"
}
}
}
}
}
errors
{
"type": "object",
"properties": {
"errors": {
"type": "array",
"items": {
"type": "object",
"properties": {
"message": {
"type": "string"
}
}
}
}
}
}
expense
{
"type": "object",
"required": [
"expenseId",
"name",
"amount",
"category",
"receiptAmount"
],
"properties": {
"name": {
"type": "string"
},
"amount": {
"$ref": "#/components/schemas/amount",
"type": "object"
},
"source": {
"type": "string"
},
"category": {
"type": "string",
"pattern": "^[A-Z_]+$"
},
"expenseId": {
"type": "string"
},
"engagement": {
"type": "object",
"properties": {
"name": {
"type": "string",
"nullable": true
},
"engagementId": {
"type": "string"
},
"engagementType": {
"type": "string",
"pattern": "^[A-Z_]+$"
}
}
},
"incurredOn": {
"type": "string",
"format": "date"
},
"receiptUrl": {
"type": "string",
"format": "uri",
"nullable": true
},
"reviewedAt": {
"type": "string",
"format": "date-time",
"nullable": true
},
"description": {
"type": "string",
"nullable": true
},
"reviewState": {
"type": "string"
},
"submittedAt": {
"type": "string",
"format": "date-time"
},
"receiptAmount": {
"$ref": "#/components/schemas/amount",
"type": "object"
}
}
}
expenses
{
"type": "array",
"items": {
"$ref": "#/components/schemas/expense"
}
}
fieldErrors
{
"type": "object",
"properties": {
"errors": {
"type": "array",
"items": {
"type": "object",
"properties": {
"field": {
"type": "string"
},
"message": {
"type": "string"
}
}
}
}
}
}
meta
{
"type": "object",
"properties": {
"page": {
"type": "integer"
},
"count": {
"type": "integer"
},
"items": {
"type": "integer"
},
"pages": {
"type": "integer"
},
"lastUrl": {
"type": "string"
},
"nextUrl": {
"type": "string"
},
"pageUrl": {
"type": "string"
},
"prevUrl": {
"type": "string"
},
"firstUrl": {
"type": "string"
}
}
}
operation
{
"type": "object",
"properties": {
"data": {
"type": "object"
},
"meta": {
"type": "object",
"properties": {
"success": {
"type": "boolean"
},
"completed": {
"type": "boolean"
}
}
},
"request": {
"type": "object",
"properties": {
"path": {
"type": "string"
},
"method": {
"type": "string"
},
"queryParams": {
"type": "object"
},
"responseCode": {
"type": "integer"
}
}
}
}
}
payroll
{
"type": "object",
"required": [
"payrollId",
"currencyCode",
"cutoffTimeForPayroll",
"state",
"payrollRecordsCount"
],
"properties": {
"state": {
"type": "string"
},
"records": {
"type": "array",
"items": {
"$ref": "#/components/schemas/payrollRecord"
}
},
"payrollId": {
"type": "string"
},
"currencyCode": {
"type": "string"
},
"payrollRecordsCount": {
"type": "integer"
},
"cutoffTimeForPayroll": {
"type": "string",
"format": "date-time",
"nullable": true
}
}
}
payrollRecord
{
"type": "object",
"required": [
"engagementId",
"currencyCode",
"monthlyPaymentsTotalAmount",
"allowancesTotalAmount",
"benefitsTotalAmount",
"bonusesTotalAmount",
"addOnsTotalAmount",
"taxesTotalAmount",
"trueUpsTotalAmount",
"oysterFeesTotalAmount",
"engagement"
],
"properties": {
"engagement": {
"type": "object",
"required": [
"name",
"cutoffMonthDay",
"engagementType"
],
"properties": {
"name": {
"type": "string"
},
"cutoffMonthDay": {
"type": "integer"
},
"engagementType": {
"type": "string"
}
}
},
"currencyCode": {
"type": "string"
},
"engagementId": {
"type": "string"
},
"taxesTotalAmount": {
"$ref": "#/components/schemas/amount"
},
"addOnsTotalAmount": {
"$ref": "#/components/schemas/amount"
},
"bonusesTotalAmount": {
"$ref": "#/components/schemas/amount"
},
"trueUpsTotalAmount": {
"$ref": "#/components/schemas/amount"
},
"benefitsTotalAmount": {
"$ref": "#/components/schemas/amount"
},
"allowancesTotalAmount": {
"$ref": "#/components/schemas/amount"
},
"oysterFeesTotalAmount": {
"$ref": "#/components/schemas/amount"
},
"monthlyPaymentsTotalAmount": {
"$ref": "#/components/schemas/amount"
}
}
}
payrolls
{
"type": "array",
"items": {
"$ref": "#/components/schemas/payroll"
}
}
phoneNumber
{
"type": "object",
"required": [
"number"
],
"properties": {
"number": {
"type": "string"
},
"countryCode": {
"type": "string",
"nullable": true
}
}
}
timeOffEngagementDetails
{
"type": "object",
"properties": {
"name": {
"type": "string"
},
"type": {
"type": "string",
"pattern": "^[A-Z_]+$"
},
"countryCode": {
"type": "string"
},
"engagementId": {
"type": "string"
}
}
}
timeOffEntitlements
{
"type": "array",
"items": {
"type": "object",
"properties": {
"taken": {
"type": "number",
"format": "float"
},
"units": {
"enum": [
"DAYS"
],
"type": "string"
},
"accrued": {
"type": "number",
"format": "float"
},
"carried": {
"type": "number",
"format": "float"
},
"upcoming": {
"type": "number",
"format": "float"
},
"engagement": {
"$ref": "#/components/schemas/timeOffEngagementDetails"
},
"adjustedAdhoc": {
"type": "number",
"format": "float"
},
"availableBalance": {
"type": "number",
"format": "float"
},
"projectedBalance": {
"type": "number",
"format": "float"
},
"annualEntitlement": {
"type": "number",
"format": "float"
}
}
}
}
timeOffRequest
{
"type": "object",
"properties": {
"type": {
"type": "string",
"pattern": "^[A-Z_]+$"
},
"state": {
"type": "string",
"pattern": "^[A-Z_]+$"
},
"reason": {
"type": "string",
"pattern": "^[A-Z_]+$"
},
"endDate": {
"type": "string",
"format": "date"
},
"startDate": {
"type": "string",
"format": "date"
},
"engagement": {
"$ref": "#/components/schemas/timeOffEngagementDetails"
},
"periodInHours": {
"type": "number",
"format": "float"
},
"lastDayDuration": {
"type": "string",
"pattern": "^[A-Z_]+$",
"nullable": true
},
"rejectionReason": {
"type": "string",
"nullable": true
},
"firstDayDuration": {
"type": "string",
"pattern": "^[A-Z_]+$"
},
"timeOffRequestId": {
"type": "string"
},
"requesterComments": {
"type": "string",
"nullable": true
}
}
}
timeOffRequests
{
"type": "array",
"items": {
"$ref": "#/components/schemas/timeOffRequest"
}
}