Lyrshop Dropshipping

Sell our catalog in your store. We ship to your customers.

Connect your Shopify, WooCommerce or custom store to Lyrshop's API. You get every published listing at a partner price, send us your orders, and we pack and ship them straight to your buyer. You keep the difference.

Loading your partner account…

API reference

JSON over HTTPS. All prices are in USD. The base URL is shown in your partner console once you're approved, and every path below is relative to it.

Authentication

curl https://api.lyrshop.com/api/v1/products \
  -H "Authorization: Bearer lyr_live_YOUR_KEY"

Requests are limited to 120 a minute per partner. Errors return a JSON body with a message: 400/422 for bad input, 401 for a bad key, 402 when the wallet is short, 403 when your account isn't active, 404 when something isn't found, 409 for a conflict and 429 when you're over the limit.

Products

GET /api/v1/products
Every published listing. Query: q (search), category, ships_to (country code), updated_since (Unix time), page, page_size (max 100). Each product has price (what you pay), retail_price (what Lyrshop charges shoppers), options (e.g. Color, Size), quantity_prices, ships_from, and shipping quotes per country when we have them.
GET /api/v1/products/{id}
One product.
POST /api/v1/shipping/quote
Shipping options and tax for a cart before you order.
curl -X POST https://api.lyrshop.com/api/v1/shipping/quote \
  -H "Authorization: Bearer lyr_live_YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"country": "US", "zip": "97201",
       "items": [{"product_id": "PRODUCT_ID", "options": {"Color": "Red", "Size": "M"}, "quantity": 2}]}'

Orders

POST /api/v1/orders
Place an order for your customer. reference is your own order number; sending the same reference again returns the order already placed instead of creating a second one, so retries are safe. shipping_method is a rate id from the quote (the cheapest is used if you leave it out). The order is paid from your wallet straight away when the balance covers it.
GET /api/v1/orders
Your orders, newest first. Query: status, page.
GET /api/v1/orders/{id}
One order, by Lyrshop order id or by your reference.
POST /api/v1/orders/{id}/pay
Pay an awaiting_payment order from your wallet after a top-up.
POST /api/v1/orders/{id}/cancel
Cancel an order before we start on it. A paid order's money goes back to your wallet.
GET /api/v1/wallet
Your balance and the last 100 wallet movements.
curl -X POST https://api.lyrshop.com/api/v1/orders \
  -H "Authorization: Bearer lyr_live_YOUR_KEY" -H "Content-Type: application/json" \
  -d '{
    "reference": "SHOP-1001",
    "items": [{"product_id": "PRODUCT_ID", "options": {"Color": "Red", "Size": "M"}, "quantity": 1}],
    "shipping_address": {"name": "Jane Doe", "address": "1 Main St", "address2": "Apt 4",
      "city": "Portland", "province": "OR", "zip": "97201", "country_code": "US",
      "phone": "+15035550100", "email": "jane@example.com"},
    "shipping_method": "standard"
  }'

Order status is one of awaiting_payment, paid, processing, shipped, delivered, cancelled or refunded. Shipped orders carry shipping_carrier, tracking_number and, when the carrier has one, tracking_url.

Webhooks

Events are order.paid, order.processing, order.shipped, order.delivered, order.cancelled, order.refunded, order.tracking_updated and ping (the test button). The body is {"id", "type", "created_at", "data": {"order": {…}}}. Each request carries a Lyrshop-Signature: t=TIMESTAMP,v1=HMAC header: an HMAC-SHA256 of TIMESTAMP + "." + raw body made with your signing secret. Check it before trusting the event, and reply with any 2xx status.

import hashlib, hmac, time

def verify(raw_body: bytes, header: str, secret: str) -> bool:
    parts = dict(item.split("=", 1) for item in header.split(","))
    expected = hmac.new(secret.encode(), parts["t"].encode() + b"." + raw_body, hashlib.sha256).hexdigest()
    fresh = abs(time.time() - int(parts["t"])) < 300
    return fresh and hmac.compare_digest(expected, parts["v1"])

We send each event once and don't retry, so poll GET /api/v1/orders?status=shipped now and then as a backstop.

Good to know