Introduction
The Louvr API provides programmatic access to your organization's data — SKUs, vendors, purchase orders, shipments, and more. All endpoints follow JSON:API conventions and are scoped to the organization tied to your API client.
Base URL
https://ledgeroto.com/api/v1
Content Type
All requests must send and accept JSON.
Content-Type: application/json
Accept: application/json
Authentication
The API uses OAuth 2.0 Client Credentials grants. Each API client is tied to a single organization. You can create and manage API clients from Settings > API Clients in the Louvr dashboard.
Obtaining an Access Token
Exchange your client ID and secret for a Bearer token:
curl -X POST https://ledgeroto.com/oauth/token \
-H "Content-Type: application/json" \
-d '{
"grant_type": "client_credentials",
"client_id": "YOUR_CLIENT_ID",
"client_secret": "YOUR_CLIENT_SECRET",
"scope": "skus:read skus:write vendors:read"
}'
Response
{
"token_type": "Bearer",
"expires_in": 2592000,
"access_token": "eyJ0eXAiOiJKV1QiLCJhbG..."
}
Using the Token
Include the token in the Authorization header of every API request:
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbG...
Pagination
All list endpoints return paginated results. Control page size with the page[size] parameter (default: 25, max: 100).
GET /api/v1/skus?page[size]=50&page[number]=2
Paginated responses include standard Laravel pagination metadata alongside the data array.
Errors
Error responses use standard HTTP status codes with a JSON body:
| Status | Meaning |
|---|---|
401 | Unauthenticated — missing or invalid token |
403 | Forbidden — token lacks the required scope, or organization not found |
404 | Resource not found |
422 | Validation error — check the errors object for details |
429 | Rate limited — too many requests |
500 | Server error |
422 Validation Error Example
{
"message": "The sku field is required.",
"errors": {
"sku": ["The sku field is required."]
}
}
Scopes
When requesting a token, specify which scopes your client needs. Each endpoint requires a specific scope.
:read scopes allow GET requests. :write scopes allow POST, PUT, and DELETE.
Organizations
Retrieve or update your organization's profile. The API client is permanently bound to one organization — there is no way to switch.
Get Organization
Scope: organizations:read
Response 200
{
"data": {
"id": "019dc4b7-...",
"type": "organizations",
"attributes": {
"name": "Acme Corp",
"icon": "building-office",
"primary_color": "#d97706",
"secondary_color": "#92400e",
"created_at": "2026-01-15T10:30:00.000000Z",
"updated_at": "2026-04-20T14:22:00.000000Z"
},
"links": {
"self": "https://ledgeroto.com/api/v1/organizations/me"
}
}
}
Update Organization
Scope: organizations:write
| Field | Type | Description |
|---|---|---|
name | string | Organization name (max 255) |
icon | string | Icon identifier (max 255) |
primary_color | string | Hex color, e.g. #d97706 (max 7) |
secondary_color | string | Hex color (max 7) |
SKUs
Manage product SKUs in your catalog. SKUs are the building blocks of purchase orders, inventory tracking, and cost analysis.
List SKUs
Scope: skus:read
Create SKU
Scope: skus:write — Returns 201 Created
| Field | Type | Description |
|---|---|---|
sku REQUIRED | string | SKU identifier (max 255) |
name REQUIRED | string | Product name (max 255) |
brand | string | Brand name |
asin | string | Amazon ASIN |
upc | string | Universal Product Code |
fnsku | string | Amazon FNSKU |
gtin | string | Global Trade Item Number |
parent_sku | string | Parent/variation SKU |
parent_asin | string | Parent ASIN for variations |
prod_grp | string | Product group |
advertised_prod_grp | string | Advertised product group |
category | string | Product category |
country_of_origin | string | Country of manufacture |
hts_code | string | Harmonized Tariff Schedule code |
material | string | Primary material |
us_duty_pct | numeric | US duty percentage (0–100) |
canada_duty_pct | numeric | Canada duty percentage (0–100) |
unit_cost_usd | numeric | Unit cost in USD |
map_price | numeric | Minimum advertised price |
moq | integer | Minimum order quantity |
is_hero | boolean | Hero product flag |
is_hero_for_ads | boolean | Hero product for advertising |
season | string | Seasonal tag |
status | string | Product status |
tags | array | Array of string tags |
weight | numeric | Product weight |
weight_uom | string | Weight unit of measure |
units_per_case | integer | Units per master case |
cases_per_pallet | integer | Cases per pallet |
unpacked_length_cm | numeric | Unpacked length (cm) |
unpacked_width_cm | numeric | Unpacked width (cm) |
unpacked_height_cm | numeric | Unpacked height (cm) |
unpacked_net_weight_kg | numeric | Unpacked net weight (kg) |
packaged_length_cm | numeric | Packaged length (cm) |
packaged_width_cm | numeric | Packaged width (cm) |
packaged_height_cm | numeric | Packaged height (cm) |
packaged_gross_weight_kg | numeric | Packaged gross weight (kg) |
Get SKU
Scope: skus:read
Update SKU
Scope: skus:write — Only include fields you want to change.
Delete SKU
Scope: skus:write — Returns 204 No Content
Response 200 (Get / List / Update)
{
"data": {
"id": "019dc4b7-...",
"type": "skus",
"attributes": {
"sku": "WG-001",
"name": "Widget Classic",
"brand": "Acme",
"asin": "B0EXAMPLE",
"upc": null,
"fnsku": "X00EXAMPLE",
"gtin": null,
"parent_sku": null,
"parent_asin": null,
"prod_grp": "Widgets",
"advertised_prod_grp": null,
"category": "Home & Kitchen",
"country_of_origin": "CN",
"hts_code": "3924.10",
"material": "Polypropylene",
"us_duty_pct": 6.5,
"canada_duty_pct": null,
"unit_cost_usd": 3.45,
"map_price": 19.99,
"moq": 500,
"is_hero": true,
"is_hero_for_ads": false,
"season": null,
"status": "active",
"tags": ["bestseller", "prime"],
"weight": 0.35,
"weight_uom": "kg",
"units_per_case": 24,
"cases_per_pallet": 60,
"unpacked_length_cm": 12.0,
"unpacked_width_cm": 8.0,
"unpacked_height_cm": 5.0,
"unpacked_net_weight_kg": 0.30,
"packaged_length_cm": 14.0,
"packaged_width_cm": 10.0,
"packaged_height_cm": 7.0,
"packaged_gross_weight_kg": 0.35,
"created_at": "2026-01-15T10:30:00.000000Z",
"updated_at": "2026-04-20T14:22:00.000000Z"
},
"links": {
"self": "https://ledgeroto.com/api/v1/skus/019dc4b7-..."
}
}
}
Vendors
Manage your supplier/vendor directory.
List Vendors
Scope: vendors:read
Create Vendor
Scope: vendors:write — Returns 201 Created
| Field | Type | Description |
|---|---|---|
name REQUIRED | string | Vendor name (max 255) |
fob_port | string | FOB port of export (max 255) |
pmt_1_pct | numeric | Payment 1 percentage (0–100) |
pmt_2_pct | numeric | Payment 2 percentage (0–100) |
pmt_3_pct | numeric | Payment 3 percentage (0–100) |
Get Vendor
Scope: vendors:read
Update Vendor
Scope: vendors:write
Delete Vendor
Scope: vendors:write — Returns 204 No Content
Locations
Manage physical and logical locations used in inventory tracking and shipment routing.
List Locations
Scope: locations:read
Create Location
Scope: locations:write — Returns 201 Created
| Field | Type | Description |
|---|---|---|
code REQUIRED | string | Short code, e.g. FBA-LAX4 (max 255) |
name REQUIRED | string | Location name (max 255) |
type REQUIRED |
string | One of: factory, in_transit, freight_forwarder, fba, awd, third_party_logistics, own_warehouse |
address_line_1 | string | Street address (max 255) |
address_city | string | City (max 255) |
address_country | string | ISO 3166-1 alpha-2 country code (max 2) |
Get Location
Scope: locations:read
Update Location
Scope: locations:write
Delete Location
Scope: locations:write — Returns 204 No Content
Manufacturers
Manage manufacturer records.
List Manufacturers
Scope: manufacturers:read
Create Manufacturer
Scope: manufacturers:write — Returns 201 Created
| Field | Type | Description |
|---|---|---|
name REQUIRED | string | Manufacturer name (max 255) |
Get Manufacturer
Scope: manufacturers:read
Update Manufacturer
Scope: manufacturers:write
Delete Manufacturer
Scope: manufacturers:write — Returns 204 No Content
Warehouses
Manage warehouse records.
List Warehouses
Scope: warehouses:read
Create Warehouse
Scope: warehouses:write — Returns 201 Created
| Field | Type | Description |
|---|---|---|
name REQUIRED | string | Warehouse name (max 255) |
Get Warehouse
Scope: warehouses:read
Update Warehouse
Scope: warehouses:write
Delete Warehouse
Scope: warehouses:write — Returns 204 No Content
Carriers
Manage shipping carriers (freight forwarders, logistics providers).
List Carriers
Scope: carriers:read
Create Carrier
Scope: carriers:write — Returns 201 Created
| Field | Type | Description |
|---|---|---|
name REQUIRED | string | Carrier name (max 255) |
Get Carrier
Scope: carriers:read
Update Carrier
Scope: carriers:write
Delete Carrier
Scope: carriers:write — Returns 204 No Content
Shipments
Manage shipments between locations. Shipments track the movement of goods from factories to freight forwarders to Amazon fulfillment centers.
List Shipments
Scope: shipments:read
Create Shipment
Scope: shipments:write — Returns 201 Created
| Field | Type | Description |
|---|---|---|
carrier_id | uuid | FK to a carrier record |
from_location_id | uuid | FK to origin location |
to_location_id | uuid | FK to destination location |
ship_method | string | One of: ocean, air, truck, rail, courier |
shipped_at | date | Departure date (ISO 8601) |
arrived_at | date | Arrival date (ISO 8601) |
expected_delivery_date | date | Expected delivery date |
estimated_cost | integer | Estimated cost in cents |
actual_cost | integer | Actual cost in cents |
notes | string | Free-text notes (max 65,535 chars) |
Get Shipment
Scope: shipments:read
Update Shipment
Scope: shipments:write
Delete Shipment
Scope: shipments:write — Returns 204 No Content
Response 200 (Get / List / Update)
{
"data": {
"id": "019dc4b7-...",
"type": "shipments",
"attributes": {
"ship_number": "SH-0042",
"ship_method": "ocean",
"shipped_at": "2026-03-01T00:00:00.000000Z",
"arrived_at": null,
"expected_delivery_date": "2026-04-15",
"estimated_cost": 450000,
"actual_cost": 0,
"notes": "Container MSKU1234567",
"carrier_id": "019dc4b7-...",
"from_location_id": "019dc4b7-...",
"to_location_id": "019dc4b7-...",
"created_at": "2026-02-28T09:15:00.000000Z",
"updated_at": "2026-03-01T12:00:00.000000Z"
},
"relationships": {
"carrier": { "data": { "id": "019dc4b7-...", "type": "carriers" } },
"from_location": { "data": { "id": "019dc4b7-...", "type": "locations" } },
"to_location": { "data": { "id": "019dc4b7-...", "type": "locations" } }
},
"links": {
"self": "https://ledgeroto.com/api/v1/shipments/019dc4b7-..."
}
}
}