This guide walks you through making your first calls against the Cayuse Inventions Public API: authenticating, listing and filtering agreements, and listing and filtering patents.
You authenticate once against the Cayuse Login Service to receive a short-lived bearer token, then include that token on every call to the Cayuse Public API.
Note: This guide is a helper for getting started. For the full and most current reference of every endpoint, parameter, and response, see the Cayuse Public API documentation on SwaggerHub. If anything in this guide ever conflicts with the SwaggerHub docs, the SwaggerHub docs are authoritative.
What's Covered
- API overview
- Get a bearer token
- Look up system types and statuses
- List and filter agreements
- List and filter patents
- Troubleshooting
- Additional resources
1. API overview
What this API gives you
| Endpoint | Purpose |
|---|---|
| GET /v1/inventions/agreements | List agreements (paginated, filterable, sortable) |
| GET /v1/inventions/agreements/{referenceNumber} | Get a single agreement by reference number |
| GET /v1/inventions/patents | List patents (paginated, filterable) |
| GET /v1/inventions/types | List system types (agreement types, patent types, date types) |
| GET /v1/inventions/statuses | List system statuses (agreement statuses, patent statuses, date statuses) |
All endpoints return JSON in this shape:
{
"data": [ ... ],
"_links": { "self": { ... }, "next": { ... }, "types": [...], "statuses": [...] },
"_metadata": { "status": 200, "pagination": { "current_page": 1, "per_page": 10, "total": 28192 }, "where": {}, "sort": [] }
}- data — the records on the current page.
- _links — paging links plus reference links for the types/statuses/group types referenced in the page.
- _metadata — page numbers, totals, and an echo of the filters and sorts that were applied.
Cayuse IDs
A Cayuse ID is the UUID Cayuse uses to identify an entity consistently across all Cayuse products (e.g. 05459d33-3a23-49c3-98d6-3436e206b0b9). Inventions responses include three kinds:
| Field | Identifies | Look up via |
|---|---|---|
| cayuse_user_id | A user account (a person) | GET /v1/users — each record has id, email, firstName, lastName. |
| cayuse_internal_unit_id | An internal organizational unit at your institution (e.g. a department, school, or lab) | GET /v1/units — each record has id, unitName, shortName, unitTypeName. |
| cayuse_external_organization_id | An external organization (e.g. a sponsor, partner company, or peer institution) | GET /v1/external-organizations — each record has id, name, acronym, organizationTypeName. |
Inside Inventions, both internal units and external organizations are referred to collectively as "groups". That's why agreement responses include a groups[] array whose entries can carry either a cayuse_internal_unit_id or a cayuse_external_organization_id.
These IDs are stable and safe to cache on your side. To find a specific entity's ID, look it up in the Cayuse UI or call the corresponding endpoint above.
Base URLs
The base URL depends on the region and environment your tenant lives in. Authentication and API calls use different hostnames:
| Region / Env | Login (signin) | API (developer) |
|---|---|---|
| UAT-US (Testing for US) | signin.uat.cayuse.com | developer.uat.cayuse.com |
| Prod-US | signin.app.cayuse.com | developer.app.cayuse.com |
| UAT-UK | signin.train-uk.cayuse.com | developer.train-uk.cayuse.com |
| Prod-UK | signin.prod-uk.cayuse.com | developer.prod-uk.cayuse.com |
| UAT-SG | signin.train-sg.cayuse.com | developer.train-sg.cayuse.com |
| Prod-SG | signin.prod-sg.cayuse.com | developer.prod-sg.cayuse.com |
| UAT-CA | signin.train-ca.cayuse.com | developer.train-ca.cayuse.com |
| Prod-CA | signin.prod-ca.cayuse.com | developer.prod-ca.cayuse.com |
| UAT-AU | signin.train-au.cayuse.com | developer.train-au.cayuse.com |
| Prod-AU | signin.prod-au.cayuse.com | developer.prod-au.cayuse.com |
The rest of this document uses Prod-US (signin.app.cayuse.com and developer.app.cayuse.com) in the examples. Substitute your region's hosts as needed.
Required headers
Every API call must include:
| Header | Value |
|---|---|
| Authorization | Bearer <your-token> |
| Content-Type | application/json |
| Accept | application/json |
| X-IDP-New-Login | true |
Rate limits
The Inventions Public API is rate-limited to 60 requests per minute and 1,000 requests per hour, per authenticated user. Calls beyond these thresholds return 429 Too Many Requests. If you expect to pull a lot of data, page through results steadily rather than fanning out parallel requests, and cache lookup data (types, statuses) on your side.
Encoding where and sort query values
The where and sort query parameters are JSON, but the values must be URL-encoded when sent. Requests with unencoded {, }, [, ], ,, or " in the query string are rejected with an empty-body 400 and no useful error message.
- With curl, use -G --data-urlencode 'where=...' (as shown in the examples throughout this guide). It encodes everything correctly.
- With most HTTP libraries, the standard query-string encoder handles this for you — pass where as a regular query parameter with the raw JSON string value.
- In Postman, even with "Encode URL automatically" enabled, the client does not encode { or }, so the request will be rejected with a 400. Pre-encode the braces yourself — replace { with %7B and } with %7D — before pasting into the URL or where query-param value. Let Postman handle quotes, brackets, and commas on its own.
For example, the where value {"people":["jane.doe@example.edu"]} needs to be sent in Postman as:
where=%7B"people":["jane.doe@example.edu"]%7D
Permissions
The API enforces the same role-based access as the Inventions UI. The user whose credentials you authenticate with needs a role that grants access to the equivalent UI pages — for example, a role that can search agreements in the UI can call /agreements via the API, and the same goes for patents.
If a call returns 403 Forbidden, ask your Cayuse administrator to check the role assigned to the API user.
2. Get a bearer token
The Cayuse Login Service issues JSON Web Tokens (JWTs) via HTTP Basic Auth. To get one, you'll need:
- The username and password of a Cayuse user in your tenant. You can use an existing user or, recommended, create a dedicated user for API access with a role that grants the data you need to read.
- Your Tenant ID (a UUID). Your Cayuse project manager will provide this.
Call the /basicauth endpoint on the signin host for your region:
USERNAME=your-api-user
PASSWORD=your-api-password
TENANT_ID=00000000-0000-0000-0000-000000000000
TOKEN=$(curl -sS --fail --basic --user "$USERNAME:$PASSWORD" \
"https://signin.app.cayuse.com/basicauth?tenant_id=$TENANT_ID")
echo "$TOKEN"
On success you'll get back an HTTP 200 with the JWT as the entire response body (no JSON wrapper). The token is roughly 1,400 bytes and starts with eyJ.... The response will look something like:
eyJraWQiOiJmNGJlN2UzYjA1OWM5YjIwNzE1YjQxNmNkMWMzNzkwOSIsImFsZyI6IlJTMjU2
In0.eyJhdXRoX3RpbWUiOjE3MjI4NTU2NTcsImNsaWVudF9pZCI6IjZydW9rNWJqZjF0aGFr
...
GyIs44GUCjgcpOXb-hcBXkCwKDB2uPawCOcrnWdVPULyodjrEOLk7LO1Twd969qPSnbnhh3w
(The real token is one continuous string with no line breaks; it's wrapped here only for readability.)
Save the token in a variable and reuse it for the next hour or so — tokens are short-lived (~1 hour) and you'll need to re-authenticate when calls start returning 401.
Common failures:
- 401 — bad username, password, or tenant_id.
- 500 — transient login-service error; retry.
Never embed credentials in client-side code, and never commit the token to source control.
3. Look up system types and statuses
Agreements and patents both have *_type_id and *_status_id fields, and the agreement-filtering where clause accepts an agreement_types array of those type IDs. The IDs are integers that vary slightly across tenants.
Cache the results on your side rather than calling the lookup endpoints on every request. The IDs themselves are stable, but the display names can be edited by Cayuse admins in your tenant's List Settings, so refresh your cache on a periodic schedule (daily is a reasonable default).
Use the parent query parameter to ask for the IDs you want. Today, the API supports the following parent values, with more expected in future versions of the API:
| parent | What it returns |
|---|---|
| 16 | Agreement types / statuses |
| 35 | Patent types / statuses |
| 161 | Agreement-date types / statuses (e.g. Effective Date, Expiration Date) |
| 36 | Patent-date types / statuses (e.g. Filing Date, Issue Date) |
Both endpoints support page and per_page query parameters for pagination (default per_page is 25; raise it to avoid extra calls).
Example
Listing agreement types (parent=16 on /types):
curl -sS -G \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "X-IDP-New-Login: true" \
"https://developer.app.cayuse.com/v1/inventions/types?parent=16&per_page=100"
Sample response:
{
"data": [
{ "id": 155, "name": "CDA Mutual" },
{ "id": 156, "name": "MTA In" },
{ "id": 157, "name": "MTA Out" },
{ "id": 158, "name": "License" },
{ "id": 432, "name": "Assignment" },
{ "id": 435, "name": "Sponsored Research" },
{ "id": 2207, "name": "MTA Mutual" }
],
"_links": { "self": { "href": "..." }, "next": { "href": "..." } },
"_metadata": { "status": 200 }
}
Swap /types for /statuses to list statuses, and swap parent=16 for any other value from the table above.
The agreement_type_id and agreement_status_id (and the patent equivalents) you see on records returned from /agreements and /patents will be IDs from these lists, so you can join records back to human-readable type and status names by caching the lookup and refreshing periodically.
4. List and filter agreements
Basic list
curl -sS -G \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "X-IDP-New-Login: true" \
"https://developer.app.cayuse.com/v1/inventions/agreements?size=10"
Each item in data[] looks like:
{
"agreement_reference_number": "A2025-0001",
"agreement_name": "Sample License Agreement",
"agreement_type_id": 158,
"agreement_status_id": 24,
"primary_investigators": [{ "name": "Jane Doe", "cayuse_user_id": "05459d33-3a23-49c3-98d6-3436e206b0b9" }],
"primary_managers": [{ "name": "John Smith", "cayuse_user_id": "8f0abd9c-e0f0-4c51-8b11-4f23543f411a" }],
"owning_organizations": [{ "name": "School of Medicine", "cayuse_internal_unit_id": "...", "cayuse_external_organization_id": null }],
"groups": [
{ "name": "Acme Corp", "group_type": "Company", "group_type_id": 1541, "cayuse_internal_unit_id": null, "cayuse_external_organization_id": "..." }
],
"url": "https://buckeye1.app.cayuse.com/inventions/agreements/35292",
"dates": {
"effective_date": { "type_id": 162, "name": "Effective Date", "value": "2025-09-24T16:16:24-04:00" },
"execution_date": { "type_id": 163, "name": "Execution Date", "value": null },
"expiration_date": { "type_id": 164, "name": "Expiration Date", "value": null }
},
"last_updated": "2025-10-04T12:01:00.000000Z"
}
Pagination
| Param | Description | Default | Max |
|---|---|---|---|
| page | Page number (1-based) | 1 | 100 |
| size | Page size | 10 | 100 |
_metadata.pagination.total tells you the total number of matching records. Use the _links.next.href / _links.previous.href URLs (or simply increment page) to walk results.
Because both page and size are capped at 100, traversal by page reaches at most the first 10,000 matching records. If your filter matches more than that, narrow the filter (e.g. by agreement_types, date range via a follow-up filter call, or agreement_name prefix) to get the records you need within the page limit.
Filtering with where
where is a URL-encoded JSON object. Today, the API accepts the following filter fields, with more expected in future versions of the API:
| Field | Type | Match behavior |
|---|---|---|
| agreement_reference_number | string | case-insensitive substring match (returns agreements where the value appears anywhere in the reference number) |
| agreement_name | string | case-insensitive substring match (returns agreements where the value appears anywhere in the name) |
| primary_investigator | string | case-insensitive substring match on the PI's name |
| agreement_types | array of integers | exact match against agreement_type_id — use IDs from Look up system types and statuses (parent=16) |
| people | array of strings | each entry must be either an email address or a Cayuse User ID (see Cayuse IDs); returns agreements where any of the listed people are associated |
| sp_projects | array of strings | matches Cayuse SP project numbers attached to the agreement |
| sp_awards | array of strings | matches Cayuse SP sponsor-award numbers attached to the agreement |
Filters are AND-combined. Within an array, values are OR-combined (agreement_types: [155, 433] returns agreements whose type is 155 or 433).
Example — find any MTA-type agreement (MTA In, MTA Out, or MTA Mutual):
curl -sS -G \
--data-urlencode 'where={"agreement_types":[156, 157, 2207]}' \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "X-IDP-New-Login: true" \
"https://developer.app.cayuse.com/v1/inventions/agreements?size=25"
See Encoding where and sort query values if you're hitting 400 errors — Postman in particular needs the braces pre-encoded.
Sorting with sort
sort is a URL-encoded JSON array of single-key objects. Today, the API supports sorting by agreement_reference_number (ascending or descending), with more sort fields expected in future versions of the API:
curl -sS -G \
--data-urlencode 'sort=[{"agreement_reference_number":"desc"}]' \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "X-IDP-New-Login: true" \
"https://developer.app.cayuse.com/v1/inventions/agreements?size=10"
Fetching a single agreement
curl -sS \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "X-IDP-New-Login: true" \
"https://developer.app.cayuse.com/v1/inventions/agreements/A2025-0001"
The path parameter is the reference number (e.g. A2025-0001), not the internal integer ID.
5. List and filter patents
Basic list
curl -sS -G \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "X-IDP-New-Login: true" \
"https://developer.app.cayuse.com/v1/inventions/patents?size=10"
Each item in data[] looks like:
{
"patent_reference_number": "P2006-141-09",
"patent_application_number": "200780023093.8",
"patent_title": "Hooded garment",
"patent_country": "China",
"patent_dates": [
{ "patent_date": "2007-04-24T04:00:00.000000Z", "patent_date_type": "Filing Date", "patent_date_type_id": 426, "patent_date_status": "Active", "patent_date_status_id": 68 },
{ "patent_date": "2009-07-01T04:00:00.000000Z", "patent_date_type": "Publication Date", "patent_date_type_id": 428, "patent_date_status": "Active", "patent_date_status_id": 68 }
],
"patent_techs": [
{ "technology_id": 306, "technology_reference_number": "T2006-141", "technology_title": "Hooded garment" }
],
"patent_type_id": 420,
"patent_status_id": 66,
"url": "https://buckeye1.app.cayuse.com/inventions/patents/727",
"last_updated": "2022-04-02T00:32:37.000000Z"
}
Pagination
Same as agreements: page and size query parameters, both capped at 100 (see agreements Pagination for details).
Filtering with where
Today, patents support filtering only by people. Additional filter fields may be added in future versions of the API.
| Field | Type | Match behavior |
|---|---|---|
| people | array of strings | each entry must be either an email address or a Cayuse User ID (see Cayuse IDs); returns patents where any of the listed people are associated |
Example — patents associated with a specific user by email:
curl -sS -G \
--data-urlencode 'where={"people":["jane.doe@example.edu"]}' \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "X-IDP-New-Login: true" \
"https://developer.app.cayuse.com/v1/inventions/patents?size=25"
Example — patents associated with a specific user by Cayuse User ID:
curl -sS -G \
--data-urlencode 'where={"people":["05459d33-3a23-49c3-98d6-3436e206b0b9"]}' \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "X-IDP-New-Login: true" \
"https://developer.app.cayuse.com/v1/inventions/patents?size=25"
You can also combine emails and Cayuse User IDs in the same array — entries that look like an email are matched against the user's email addresses, and everything else is matched against the cayuse_user_id:
curl -sS -G \
--data-urlencode 'where={"people":["jane.doe@example.edu","05459d33-3a23-49c3-98d6-3436e206b0b9"]}' \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "X-IDP-New-Login: true" \
"https://developer.app.cayuse.com/v1/inventions/patents?size=25"
6. Troubleshooting
| Symptom | Likely cause |
|---|---|
| 401 Unauthorized from /basicauth | Bad credentials or wrong tenant_id. |
| 401 Unauthorized from developer.<env>.cayuse.com | Token has expired (~1 hour lifetime). Re-authenticate. |
| 403 Forbidden | The authenticated user's role lacks the required permission. See Permissions. |
| 400 with an empty body | Unencoded {, }, [, ], ,, or " in the where or sort query string. See Encoding where and sort query values. |
| 422 with errors | Validation rejected the request — the response body lists which field is invalid (e.g. unknown where key, bad parent for /types). |
| 422 with "may not be greater than 100" | page or size exceeded the cap of 100. See Pagination. |
If you hit a problem you can't resolve from the response, capture the full response (curl's -i flag prints headers + body) and share it with your Cayuse contact — the x-amzn-requestid response header in particular helps us trace the request on our side.
7. Additional resources
- Cayuse Public APIs Help Center — broader authentication and usage documentation that applies across all Cayuse Public APIs (Inventions, Sponsored Projects, etc.).
- Cayuse Public API Swagger / OpenAPI spec — the full machine-readable spec for every Cayuse Public API endpoint, including the Inventions endpoints covered in this guide.