Skip to content

Snipe-IT License Seats API Endpoint Does Not Return All Seats Without Pagination #19

Description

@tianma3

API Endpoint Affected: /api/v1/licenses/{id}/seats
Reference Documentation: https://snipe-it.readme.io/reference/licensesidseats

Issue Description

The Snipe-IT API endpoint for retrieving license seats (/api/v1/licenses/{id}/seats) does not return all unique seat IDs for a license as described in the documentation. Instead, it appears to paginate results by default (likely with a hidden or undocumented limit), returning only a subset of seats. This requires manual implementation of pagination (using parameters like offset and limit) to fetch all seats, which is not mentioned in the endpoint-specific documentation. This leads to incomplete data retrieval when calling the endpoint without pagination parameters, potentially causing errors in applications relying on the API to return complete results (e.g., "no available seats" errors when seats exist on subsequent pages).

This inconsistency between the documented behavior ("returns all unique Seat IDs") and actual implementation hinders development and requires workarounds, such as custom pagination logic in client code.

Reproduction Steps

  1. Set up or access a Snipe-IT instance with a license that has a large number of seats (e.g., >50, assuming a default limit around 50-100).
  2. Authenticate with the API using a valid Bearer token.
  3. Make a GET request to the endpoint without any query parameters:
    GET /api/v1/licenses/{license_id}/seats
    (Replace {license_id} with a valid license ID having many seats.)
  4. Observe the response JSON, noting the number of seats returned in the rows array and the total field.
  5. If the total is greater than the number of items in rows, confirm that not all seats are returned in a single call.
  6. To fetch additional seats, add pagination parameters (e.g., ?offset=50&limit=50) and repeat the request to see subsequent pages.

Example using curl:

curl -H "Authorization: Bearer {your_api_token}" "https://your-snipeit-instance.com/api/v1/licenses/{license_id}/seats"

Expected Behavior

Based on the documentation (https://snipe-it.readme.io/reference/licensesidseats), the endpoint should return all unique Seat IDs for the specified license in a single response, without requiring pagination parameters. The response should include a complete list in the rows array, matching the total count, regardless of the number of seats.

If pagination is intended, the documentation should explicitly describe supported parameters (e.g., limit, offset) and default values, similar to other endpoints like /users or general API throttling notes.

Actual Behavior

  • The endpoint returns only a paginated subset of seats (e.g., first 50-100 seats, based on a default limit).
  • The total field in the response indicates the full count, but the rows array contains only the current page's seats.
  • To retrieve all seats, manual pagination is required using undocumented parameters like offset and limit (inferred from general Snipe-IT API patterns, such as "standard pagination using the offset parameter" mentioned in API throttling docs: https://snipe-it.readme.io/reference/api-throttling).
  • Without pagination, applications may incorrectly assume no more seats exist, leading to errors like "no available seats for license ID {id}" when unassigned seats are on later pages.

Technical Details

  • API Version: v1 (as per the endpoint path).
  • Request Method: GET.
  • Query Parameters Used in Workaround:
    • offset: Starting point for results (e.g., 0 for first page).
    • limit: Number of results per page (e.g., 500; no documented maximum).
    • Other inferred parameters: order (e.g., "asc"), sort (e.g., "name"), though not always necessary.
  • Response Format: JSON object with total (integer) and rows (array of seat objects, each with id, method.license_id, method.assigned_user.record, etc.).
  • Environment:
    • Tested on a Snipe-IT instance.
    • Client: Go application using HTTP requests.
  • Workaround Implemented: Manual pagination loop in client code:
    • Start with page=1, size=500.
    • Increment page until an unassigned seat is found or rows length < size.
    • Example: https://ledger.snipe-it.io/api/v1/licenses/{id}/seats?page=4&size=500&order=asc&sort=name.
  • Related Documentation Issues:
  • Impact: Affects integrations processing large licenses (e.g., >500 seats), causing incomplete data and requiring custom code to paginate.

Suggested Fix:

  • Update the endpoint to optionally return all seats (e.g., with ?all=true or no limit by default if feasible).
  • Document pagination parameters (limit, offset, defaults) explicitly in the /licenses/{id}/seats reference.
  • If possible, add a note on maximum page size to avoid server strain.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions