API fundamentals
Learn about the Gusto API, including pagination, rate limits, and scopes
The Gusto Embedded API behavior is built on core fundamentals that apply to every endpoint.
These determine how information is displayed, how we handle identical requests, the number of requests you can make per minute, and the actions your application can take.
Pagination
To enhance API performance, several collection endpoints support pagination. To use this feature, add a page and optionally a per parameter to the URL query string.
For example https://api.gusto.com/v1/companies/abc123/employees?page=2&per=5
returns the second page of five employees for the company identified by UUID abc123
. If the per parameter is not included, the API returns 25 records per page, unless otherwise specified.
Each endpoint that supports pagination will be mentioned in its respective documentation.
Paginated responses
When pagination parameters are included, metadata will be returned in the response headers, as in this example:
When pagination parameters are included, metadata will be returned in the response headers, as in this example:
X-Page: 3
X-Total-Count: 542
X-Total-Pages: 22
X-Per-Page: 20
Header | Description | Example |
---|---|---|
X-Page | The current page being returned | 3 |
X-Total-Count | Total number of records in the full collection | 542 |
X-Total-Pages | Total number of pages for this collection | 22 |
X-Per-Page | Number of records returned per page | 20 |
Cursor-based pagination
Some APIs support cursor-based pagination for more consistent results, particularly with real-time data models. Instead of page
and per
, cursor-based pagination uses starting_after_uuid
and limit
. For example:
https://api.gusto.com/v1/events?starting_after_uuid=10ac74e7-d6f0-46c0-9697-8ec77ab475ba&limit=5
Cursor-paginated APIs include the X-Has-Next-Page
header, which will have a value either of true or false. For example, X-Has-Next-Page: true
. If X-Has-Next-Page
is true
, more results will be available. Use the UUID of the last record from the current response as the next starting_after_uuid
value.
Reliability
We use two main strategies to achieve operationally safe behavior: idempotency and optimistic version control. Both improve reliabilityβidempotency deals with retries, while version control deals with concurrency and versioning.
Use case | Strategy | HTTP method | Purpose |
---|---|---|---|
Creating resources | Idempotency key | POST | Retry safety: Ensures multiple identical requests have the same effect, preventing duplicate creations when retrying the same request. e.g. when timeouts happen during the create call. |
Updating resources | Optimistic version control | PUT | Consistency safety: Prevents concurrent conflicting updates to the same resource. Ensures updates only apply if the data hasnβt changed since the last time it was fetched. |
Idempotency
In API design, idempotency ensures that performing the same logical operation multiple times produces the same final result.
It protects your integration from network retries, client crashes, and concurrent updates that could otherwise cause duplicates or data inconsistencies.
The goal is to make each operation safe to retry.
In HTTP semantics, idempotency means that making the same request multiple times produces the same end state.
DELETE
is inherently idempotent: repeating the call will either delete the resource, or cause a "not found" error. You can't delete more than once.PUT
andPOST
are not naturally idempotent, and need special mechanisms to ensure operational safety.GET
is read-only and always surfaces the latest state of a resource; it never changes the serverβs data and therefore doesnβt require idempotency handling.
Best practices
- Always generate a new idempotency key for every unique create action.
- Reuse the same idempotency key or version only when retrying the same request payload.
- Log and store idempotency keys in your system to trace retry behavior.
- Avoid sharing the same keys across different endpoints.
Optimistic version control
At Gusto we have object-based versionsβessentially snapshots of a given resourceβto process concurrent updates correctly, ensuring data integrity in a multi-user environment. It is a form of optimistic concurrency control, where the system 'assumes' that conflicts are rare and only checks for them at the time of an update.
For example: Letβs say you give Frank (ID 7) a $200 bonus, but another app has already given Frank a $150 bonus. Your request to update the payroll sets the bonus to 200.00, overwriting the previous bonus. Frank is now set to receive a $200 bonus instead of the combined $350.
To prevent this, all updateable objects returned by the Gusto API include a version
field. This version
is calculated based on all updatable attributes of this object and its child objects.
To successfully update a record youβve retrieved, you must include this same version
number in your PUT request. If another process has already updated the record and changed the version
number, your request will be rejected with a 409 Conflict
HTTP status.
This ensures that:
- The object that you are trying to update did not change underneath.
- Your updates will only overwrite the targeted data, instead of allowing overwriting other changes that may have occurred in the system since you last fetched the object.
- Youβre prevented from accidentally operating on a stale object version.
The version only changes when an updatable attribute changes. It is not intended for general change detection and should only be used to prevent race conditions and the overwriting of data.
Rate limits
Rate limits are scoped per application-user pair. Each application can make 200 requests per minute per user. If you exceed this rate, Gusto will return a 429: Too Many Requests
error.
Limits are enforced in a rolling 60-second window. The window starts when your first API call is made and resets 60 seconds later. A new window begins with your next API request.
API response headers
The following headers are now available to use when handling rate limiting programmatically:
Header | Description |
---|---|
'Retry-After' | The number of seconds until the rate limit window resets |
'X-RateLimit-Limit' | The total number of requests allowed in the rate limit window |
'X-RateLimit-Remaining' | The number of requests remaining in the rate limit window |
'X-RateLimit-Reset' | The datetime when the rate limit window will reset |
Scopes
API scopes control what data your app can access. Each scope is named by resource and action, such as employees:read
.
We currently support two types of actions:
read
: Read data from a resourcewrite
: Create, edit, or delete a resource
Requesting and viewing scopes
You can view your applicationβs current scopes in the Developer Portal.
Before going to production, your application will be granted scopes based on your Embedded Payroll use case. Requests outside your assigned scopes will return a 403 Forbidden
error.
To request scope changes, contact your Technical Solutions representative. We recommend requesting only the scopes you need to build confidence and trust with your users.
Updated about 5 hours ago