For AI agents: a documentation index is available at the root level at /llms.txt and /llms-full.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Dashboard
DocsAPI Reference
DocsAPI Reference
  • Getting Started
    • Welcome
    • Authentication
Dashboard
LogoLogo
On this page
  • Authentication
  • Creating an API key
  • Scopes
  • Available scopes
  • Rate limits
  • Rate limit headers
  • Handling 429 Too Many Requests
  • Environments
  • Example: Complete authenticated request
  • Security best practices
Getting Started

Authentication

Secure your API requests with API keys and scopes
Was this page helpful?
Edit this page
Previous
Built with

Authentication

The Ply API uses API key authentication. Every request must include your API key in the API_KEY header.

$curl -X GET "https://api.getply.com/api/v1/materials" \
> -H "API_KEY: YOUR_API_KEY"

API keys grant access to your business data. Treat them like passwords — never commit them to source control or expose them in client-side code.

Creating an API key

1

Open the Ply dashboard

Go to app.getply.com and sign in with an Owner or Admin account.

2

Navigate to API settings

Go to Settings > Integrations > API Keys.

3

Create a new key

Click Create API Key, give it a descriptive name (e.g., “ERP Sync” or “Dashboard Integration”), and select the scopes your integration needs.

4

Copy your key

Your full API key is shown only once. Copy it and store it securely (e.g., in a secrets manager or environment variable).

Scopes

API keys are scoped to limit what they can access. When creating a key, select only the scopes your integration needs. A key without the required scope for an endpoint will receive a 403 Insufficient Scope error.

Available scopes

ScopeAccess
materials:readList and get materials, variations
materials:writeCreate, update, delete materials
kits:readList and get kits, kit materials
kits:writeCreate, update, delete kits
purchase_orders:readList and get purchase orders, line items
purchase_orders:writeCreate, update, delete purchase orders and items
suppliers:readList and get suppliers
suppliers:writeCreate, update, delete suppliers
categories:readList and get categories, tags, supplier categories
categories:writeCreate, update, delete categories and tags
field_requests:readList and get field requests
field_requests:writeCreate, update, delete field requests; change status/priority
pick_lists:readList and get pick lists, pick list materials
pick_lists:writeCreate, update, delete pick lists and materials
returns:readList and get returns, return items
returns:writeCreate, update, delete returns and items
rfqs:readList and get RFQs, RFQ suppliers
rfqs:writeCreate, update RFQs; manage suppliers
inventory:readView inventory history and snapshots
inventory:writeWrite access for inventory history
inventory_counts:readList and get inventory counts and count items
inventory_counts:writeCreate and update inventory counts
locations:readList and get locations, location materials
users:readList and get users
reports:readAccess low-stock, dead-shelf, usage, and variance reports

Write scopes implicitly include read access for the same resource. A key with materials:write can also read materials.

Rate limits

API requests are rate-limited per business to ensure fair usage across all integrations.

LimitWindowDescription
60 requestsPer minuteBurst limit for short time windows
10,000 requestsPer dayDaily quota across all endpoints

All API keys belonging to the same business share a single rate limit pool. Creating multiple keys does not increase your limits.

Rate limit headers

Every response includes headers showing your current usage:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57
X-RateLimit-Reset: 45
HeaderDescription
X-RateLimit-LimitMaximum requests allowed in the current window
X-RateLimit-RemainingRequests remaining before throttling
X-RateLimit-ResetSeconds until the rate limit window resets

Handling 429 Too Many Requests

When you exceed the rate limit, the API returns:

1{
2 "code": "RATE_LIMIT_EXCEEDED",
3 "message": "Rate limit exceeded. Please retry after 12 seconds.",
4 "status": 429,
5 "timestamp": "2026-03-20T14:30:00",
6 "path": "/api/v1/materials"
7}

The Retry-After header tells you how many seconds to wait before retrying:

Retry-After: 12

Implement exponential backoff in your integration. Start with the Retry-After value, then double the wait time on consecutive 429s.

Environments

EnvironmentBase URLPurpose
Productionhttps://api.getply.com/api/v1Live business data
Sandboxhttps://sandbox-api.getply.com/api/v1Test integrations before going live

Use separate API keys for each environment. Sandbox keys do not work in production and vice versa.

Example: Complete authenticated request

$curl -X GET "https://api.getply.com/api/v1/purchase-orders?page=0&size=10&sort=createdAt,desc" \
> -H "API_KEY: YOUR_API_KEY" \
> -H "Accept: application/json"
1{
2 "data": [
3 {
4 "id": "550e8400-e29b-41d4-a716-446655440000",
5 "orderNumber": "PO-1042",
6 "status": "CONFIRMED",
7 "supplier": {
8 "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
9 "name": "Ferguson Enterprises"
10 },
11 "location": {
12 "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
13 "name": "Main Warehouse"
14 },
15 "totalCost": 1249.50,
16 "createdAt": "2026-03-15T09:22:00",
17 "updatedAt": "2026-03-18T14:05:30"
18 }
19 ],
20 "pagination": {
21 "page": 0,
22 "size": 10,
23 "totalElements": 47,
24 "totalPages": 5
25 }
26}

Security best practices

  • Rotate keys regularly — revoke and recreate keys periodically
  • Use minimum scopes — only grant the access your integration needs
  • Store keys securely — use environment variables or a secrets manager, never hardcode
  • Monitor usage — check the API Keys page in the dashboard for usage metrics
  • Use sandbox for development — test against sandbox before pointing at production