Skip to main content

Documentation Index

Fetch the complete documentation index at: https://developers.paperlink.online/llms.txt

Use this file to discover all available pages before exploring further.

The Paperlink API currently exposes endpoints for managing your team’s product catalog. All endpoints are under the base URL https://app.paperlink.online/api/v1 and require a valid Bearer token in the Authorization header. The full machine-readable OpenAPI specification is available at app.paperlink.online/api/v1/openapi.json.
Read-only keys (scope READ_ONLY) can only call GET endpoints. Attempting a POST, PATCH, or DELETE request with a Read-only key returns 403 scope_insufficient.

Products

Products are the items in your team’s catalog that appear as line items on invoices and estimates. The products endpoints let you read and manage that catalog programmatically.

List products

Retrieves a paginated list of products for your team.
GET /api/v1/products
Query parameters
status
string
default:"active"
Filter by product status. Accepted values: active, archived, all.
limit
integer
default:"20"
Number of products to return. Minimum 1, maximum 100.
after
string
Cursor for pagination. Pass the nextCursor value from a previous response to fetch the next page.
Example request
curl "https://app.paperlink.online/api/v1/products?status=active&limit=5" \
  -H "Authorization: Bearer <your-token>"
Example response
{
  "data": {
    "data": [
      {
        "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "name": "Web Design",
        "unitPrice": 120.00,
        "currency": "USD",
        "description": "Custom web design service",
        "sku": "WD-001",
        "taxRate": 20.0,
        "type": "SERVICES",
        "unitOfMeasure": "hr",
        "status": "active",
        "createdAt": "2025-01-15T10:00:00.000Z",
        "updatedAt": "2025-03-22T14:30:00.000Z"
      }
    ],
    "hasMore": true,
    "nextCursor": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}
Response fields
data.data
array
Array of product objects.
data.hasMore
boolean
true if there are more pages to fetch. Pass data.nextCursor as the after parameter to retrieve the next page.
data.nextCursor
string | null
Cursor to pass as after in the next request. null when you have reached the last page.

Get a product

Retrieves a single product by its ID.
GET /api/v1/products/{id}
Path parameters
id
string
required
The UUID of the product to retrieve.
Example request
curl "https://app.paperlink.online/api/v1/products/a1b2c3d4-e5f6-7890-abcd-ef1234567890" \
  -H "Authorization: Bearer <your-token>"
Example response
{
  "data": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "name": "Web Design",
    "unitPrice": 120.00,
    "currency": "USD",
    "description": "Custom web design service",
    "sku": "WD-001",
    "taxRate": 20.0,
    "type": "SERVICES",
    "unitOfMeasure": "hr",
    "status": "active",
    "createdAt": "2025-01-15T10:00:00.000Z",
    "updatedAt": "2025-03-22T14:30:00.000Z"
  }
}
Returns 404 product_not_found if the product does not exist in your team’s catalog or does not match the key’s mode (Live vs. Test).

Create a product

Creates a new product in your team’s catalog.
POST /api/v1/products
Requires a Read & Write key. This endpoint supports idempotent requests: pass an Idempotency-Key header to safely retry without creating duplicates. Request body
name
string
required
Product name. Maximum 255 characters.
unitPrice
number
required
Unit price as a non-negative number. For example, 120.00.
currency
string
required
Three-letter ISO 4217 currency code. For example, "USD", "EUR", "UAH".
description
string
Optional description. Maximum 2000 characters.
sku
string
Optional stock-keeping unit identifier. Must be unique within your team’s catalog. Maximum 100 characters.
taxRate
number
Optional tax rate as a percentage between 0 and 100. For example, 20 for 20% VAT.
type
string
Optional product classification. Accepted values: GOODS, SERVICES.
unitOfMeasure
string
Optional unit of measure. Accepted values include hr, day, pcs, ea, kg, m, , service, project, license, seat, and many more. See the full list in the interactive API docs.
Example request
curl -X POST https://app.paperlink.online/api/v1/products \
  -H "Authorization: Bearer <your-token>" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: create-web-design-2025-04-30" \
  -d '{
    "name": "Web Design",
    "unitPrice": 120.00,
    "currency": "USD",
    "description": "Custom web design service",
    "sku": "WD-001",
    "taxRate": 20,
    "type": "SERVICES",
    "unitOfMeasure": "hr"
  }'
Example response (201 Created)
{
  "data": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "name": "Web Design",
    "unitPrice": 120.00,
    "currency": "USD",
    "description": "Custom web design service",
    "sku": "WD-001",
    "taxRate": 20.0,
    "type": "SERVICES",
    "unitOfMeasure": "hr",
    "status": "active",
    "createdAt": "2025-04-30T09:00:00.000Z",
    "updatedAt": "2025-04-30T09:00:00.000Z"
  }
}
The response includes a Location header pointing to the new product: Location: /api/v1/products/{id}. Returns 409 duplicate_sku if another active product in your catalog already uses the same SKU.

Update a product

Updates one or more fields on an existing product. Only the fields you include in the request body are changed — omitted fields keep their current values.
PATCH /api/v1/products/{id}
Requires a Read & Write key. Supports the Idempotency-Key header. Path parameters
id
string
required
The UUID of the product to update.
Request body All fields are optional. Include only the fields you want to change.
name
string
New product name. Maximum 255 characters.
unitPrice
number
New unit price as a non-negative number.
currency
string
New three-letter ISO 4217 currency code.
description
string | null
New description. Pass null to clear the existing description.
sku
string | null
New SKU. Pass null to clear the existing SKU. Must be unique within the catalog if provided.
taxRate
number | null
New tax rate (0-100). Pass null to clear the existing tax rate.
type
string
New product type. Accepted values: GOODS, SERVICES.
unitOfMeasure
string
New unit of measure.
Example request
curl -X PATCH "https://app.paperlink.online/api/v1/products/a1b2c3d4-e5f6-7890-abcd-ef1234567890" \
  -H "Authorization: Bearer <your-token>" \
  -H "Content-Type: application/json" \
  -d '{"unitPrice": 140.00, "taxRate": null}'
Returns 200 with the updated product object, 404 product_not_found if the product does not exist, or 409 duplicate_sku on a SKU conflict.

Archive a product

Archives a product, removing it from the active catalog. Archived products are retained for historical records on existing invoices but no longer appear when creating new documents.
DELETE /api/v1/products/{id}
Requires a Read & Write key. Path parameters
id
string
required
The UUID of the product to archive.
Example request
curl -X DELETE "https://app.paperlink.online/api/v1/products/a1b2c3d4-e5f6-7890-abcd-ef1234567890" \
  -H "Authorization: Bearer <your-token>"
Returns 204 No Content on success. Returns 404 product_not_found if the product does not exist, or 409 already_archived if the product has already been archived.
Archiving a product does not delete it. Archived products remain visible when you filter by status=archived or status=all. This preserves the integrity of existing invoices that reference the product.

Error responses

All errors follow a consistent structure:
{
  "error": {
    "type": "validation_error",
    "code": "invalid_body",
    "message": "Validation failed",
    "details": [...],
    "request_id": "req_01j..."
  }
}
error.type
string
High-level error category: authentication_error, permission_error, not_found_error, validation_error, conflict_error, rate_limit_error, or server_error.
error.code
string
Machine-readable error code such as invalid_token, scope_insufficient, product_not_found, duplicate_sku, or rate_limit_exceeded.
error.message
string
Human-readable description of the error.
error.details
array
Present on validation_error responses. Each entry describes one validation failure, including the field path and the constraint that was violated.
error.request_id
string
Unique identifier for this request. Include this ID when contacting support so the request can be traced in server logs.

Idempotency

Write endpoints (POST and PATCH) accept an optional Idempotency-Key header. If you send the same key and request body more than once, the API returns the original response from the first successful request rather than executing the operation again. Use this to safely retry requests after a network failure without creating duplicate records.
curl -X POST https://app.paperlink.online/api/v1/products \
  -H "Authorization: Bearer <your-token>" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: unique-operation-id-here" \
  -d '{"name": "Consulting", "unitPrice": 200, "currency": "EUR"}'
Use a UUID or a deterministic string derived from the operation context as your idempotency key, for example create-product-${sku}-${teamId}. Avoid reusing the same key for different operations.

Where to go next

API overview

Understand modes, scopes, and rate limits

Authenticate with the API

Create an API key and learn how to use Bearer token auth

Clients and products

Manage your product catalog inside Paperlink

Integrations

Connect Paperlink with Slack, AI assistants, and your own tools