Back to docs

Publisher API

Verify a buyer's proof of purchase, pull your own sales data, and gift assets — all programmatically. The verify endpoint is field-compatible with Unity's Publisher API, so porting an existing Unity license-gate integration is nearly a base-URL swap.

The data endpoints (verify, list, summary) require DevLoot Pro. Gifting works on any tier up to your gift quota. Manage everything from your API dashboard.

Authentication

Every request authenticates with a Publisher API key, scoped to a single storefront. A request can only ever read or affect that storefront's data. Pass the key one of two ways:

Recommended — Authorization header

curl https://thedevloot.com/api/publisher/v1/invoices/verify?invoice=DL-2026-000123 \
  -H "Authorization: Bearer dlpk_live_xxxxxxxx..."

Unity-compatible — query parameter

For drop-in compatibility with an existing Unity Publisher API integration that sends the key as ?key=:

curl "https://thedevloot.com/api/publisher/v1/invoices/verify?key=dlpk_live_xxxx...&invoice=DL-2026-000123"

The header form is preferred — query-string keys leak into server logs and browser history. Both work identically.

Getting a key

  1. Open your API dashboard.
  2. Click Generate key, optionally label it.
  3. Copy the key — it's shown once and never retrievable again. Store it as a secret.

Keys look like dlpk_live_…. Revoke any key from the same dashboard; revocation is immediate.

Verify invoices

GET /api/publisher/v1/invoices/verify

The proof-of-purchase endpoint. Pass one or more invoice numbers (comma-separated, up to 50). Returns the matching invoices that belong to your storefront. Unknown or other publishers' invoice numbers are silently omitted (never an error, never another publisher's data).

Parameters

  • invoice — required. One number, or several comma-separated.

Example

GET /api/publisher/v1/invoices/verify?invoice=DL-2026-000123,DL-2026-000124
Authorization: Bearer dlpk_live_xxxx...

200 OK
{
  "invoices": [
    {
      "invoice": "DL-2026-000123",
      "package": "GameCatalyst",
      "package_id": "prod_1773701493669_dwkt0r",
      "date": "2026-05-02",
      "refunded": "No",
      "quantity": "1",
      "price_exvat": "40.00",
      "currency": "USD",
      "downloaded": "Yes",
      "other_license": "No"
    }
  ]
}

List / filter invoices

GET /api/publisher/v1/invoices

Returns your invoices, newest first. Use it for your own reporting or to reconcile sales by asset.

Parameters (all optional)

  • package — filter by asset display name(s), comma-separated, substring match.
  • from, to — date range, YYYY-MM-DD, inclusive.
  • limit — page size, default 50, max 200.
  • cursor — pass back nextCursor from the prior response to paginate.
GET /api/publisher/v1/invoices?package=GameCatalyst,StormWeave&from=2026-04-01
Authorization: Bearer dlpk_live_xxxx...

200 OK
{ "invoices": [ /* …same shape as verify… */ ], "nextCursor": "DL-2026-000088" }

Sales summary

GET /api/publisher/v1/sales/summary

Monthly roll-up for trend tracking: gross, refunds, net, unit counts, plus a per-package breakdown. Amounts are in minor units (cents) and are not currency-converted — mixed-currency sales stay separable via byCurrency.

GET /api/publisher/v1/sales/summary?from=2026-01-01
Authorization: Bearer dlpk_live_xxxx...

200 OK
{
  "totals": { "gross": 128000, "refunds": 4000, "net": 124000, "units": 32 },
  "byCurrency": { "USD": 128000 },
  "monthly": [
    { "month": "2026-04", "gross": 64000, "refunds": 0, "net": 64000, "units": 16, "refundedCount": 0 }
  ],
  "byPackage": [
    { "package": "GameCatalyst", "gross": 96000, "units": 24, "refundedCount": 1 }
  ]
}

Gifting

POST /api/publisher/v1/gifts

Grant a license for one of your own products to a user, free. The asset lands in their Library and generates a $0.00 invoice you can verify through this same API — which makes gifting a convenient way to test your integration end-to-end.

Body

  • productId — must be one of your products.
  • recipientEmail — the recipient must already have a DevLoot account.
POST /api/publisher/v1/gifts
Authorization: Bearer dlpk_live_xxxx...
Content-Type: application/json

{ "productId": "prod_1773701493669_dwkt0r", "recipientEmail": "tester@example.com" }

200 OK
{ "success": true, "invoice": "DL-2026-000200", "recipientUid": "…", "remainingThisWindow": 4, "limit": 5 }

Quota

Gift volume is metered by DevLoot (it consumes storage + API resources):

  • Free — 5 gifts per rolling 30 days.
  • Pro — 100 gifts per rolling 30 days.

Check current usage with GET /api/publisher/v1/gifts:

200 OK
{ "tier": "free", "used": 1, "limit": 5, "remaining": 4, "windowDays": 30 }

Invoice field reference

The object returned by verify and list:

FieldTypeDescription
invoicestringInvoice number, e.g. DL-2026-000123.
packagestringDisplay name of the asset (matches your listing name).
package_idstringStable product id.
datestringPurchase date, YYYY-MM-DD.
refunded'Yes' | 'No'Has the purchase been refunded or charged back?
reasonstring (optional)Present only when refunded — 'refund' or 'chargeback'.
quantitystringNumber of licenses purchased.
price_exvatstringLine total excluding tax, decimal (Stripe handles VAT at checkout).
currencystringISO currency of price_exvat (e.g. USD).
downloaded'Yes' | 'No'Has the buyer downloaded the asset yet?
other_license'Yes' | 'No'Does the buyer hold a separate valid license for this product?

Errors

StatuscodeMeaning
400missing_invoice / bad_bodyRequired parameter or body missing.
402pro_requiredEndpoint needs DevLoot Pro — upgrade your storefront.
403invalid_api_keyNo or unknown API key.
403not_your_productGifting a product that isn’t yours.
404recipient_not_foundGift recipient has no DevLoot account yet.
429gift_quota_* / rate_limitedGift quota hit, or too many requests.
500internalServer error — retry shortly.

Rate limits

  • verify — 120 requests / minute.
  • invoices (list) — 60 / minute.
  • sales/summary — 30 / minute.
  • gifts — 20 / minute (plus the 30-day quota above).

Exceeding a limit returns 429. Limits are per-IP.

Migrating from Unity's Publisher API

If you already gate content against Unity's invoice-verify endpoint, the move is mostly mechanical:

  • Base URL → swap Unity's verify URL for https://thedevloot.com/api/publisher/v1/invoices/verify.
  • Key → use your DevLoot key. Both ?key= and Authorization: Bearer are accepted.
  • Response fields are identical (invoice, package, package_id, refunded, quantity, price_exvat, currency, downloaded, other_license), so your package-name → role mapping works unchanged.
  • Batch verify works the same — comma-separate invoice numbers in one call.
  • Watch out: DevLoot invoice numbers are formatted DL-2026-000123, not Unity's numeric ids. If your plugin validates invoice numbers with a digits-only regex, loosen it to accept the DL- prefix.
  • VAT — DevLoot lets Stripe handle tax at checkout, so price_exvat is simply your pre-tax line price. There's no deprecated price_usd_exvat field.

Questions or a field you need that isn't here? Reach us via Contact. We read every API request.