Skip to content

Publinza API

v1

Read your account, the Marketplace, your orders and invoices, and - for publishers - your websites and the orders on them. Version 1 is read-only.

Getting access

API access requires approval. An administrator reviews every request before any key can be created.

  1. Request access. In Account → API access, say what your integration does and choose the scopes it needs.
  2. Admin approval. An administrator approves the request - for some or all of the scopes you asked for - or explains why not. Until then the request shows as pending.
  3. Create a key. Once approved, create keys on the same page, each with some or all of your approved scopes.
  4. Use approved scopes. Every request is checked against your approval as it stands now. If access is revoked, your keys are revoked with it; if a scope is removed, keys holding it are revoked. Revoked keys stay revoked.

Authentication

Once your access is approved, create an API key in your account and send it as a bearer token. A key is shown once; Publinza stores only a hash of it. A key acts as you and never more: each scope reads only your own data, and you can rotate or revoke a key at any time.

curl -H "Authorization: Bearer pz_xxxxxxxxxxxx_..." \
  https://YOUR-PUBLINZA-HOST/api/v1/orders?limit=20

There is no administrator API. The machine-readable description is at /api/v1/openapi.json (OpenAPI 3.1).

Scopes

Explicit, read-only. A key holds only scopes approved for its owner's account that the account's roles allow.

  • account:read - Read your own account: name, email address and account type. (any account)
  • marketplace:read - Browse approved Marketplace websites and their offers, as you can on the website. (advertiser accounts)
  • orders:read - Read the orders you placed, their status and their invoices. (advertiser accounts)
  • websites:read - Read your own websites and offers, and their review and publication state. (publisher accounts)
  • publisher:orders:read - Read orders placed on your websites, what they pay you and which need your action. (publisher accounts)

Endpoints

  • GET/api/v1no key

    The API version and where its documentation is. No key needed.

    {
      "name": "Publinza API",
      "version": "v1",
      "documentation": "/developers",
      "openapi": "/api/v1/openapi.json"
    }
  • GET/api/v1/openapi.jsonno key

    This API as an OpenAPI 3.1 document. No key needed.

    {
      "openapi": "3.1.0"
    }
  • GET/api/v1/categoriesno key

    The active Marketplace categories. No key needed.

    {
      "data": [
        {
          "name": "Technology",
          "slug": "technology"
        }
      ]
    }
  • GET/api/v1/meaccount:read

    The account the API key belongs to.

    {
      "data": {
        "id": "cm...",
        "name": "Ada",
        "email": "ada@example.com",
        "emailVerified": true,
        "accountType": "ADVERTISER",
        "createdAt": "2026-01-01T00:00:00.000Z"
      }
    }
  • GET/api/v1/marketplace/websitesmarketplace:read

    Approved Marketplace websites and their offers at the prices advertisers see, 20 per page. The same filters as the Marketplace page.

    Parameters: q (query) - Search text.; category (query) - A category slug.; type (query) - GUEST_POST or LINK_INSERTION.; minPrice (query) - Minimum price, in whole dollars.; maxPrice (query) - Maximum price, in whole dollars.; page (query) - Page number, from 1.

    {
      "data": [
        {
          "id": "cm...",
          "name": "Example Media",
          "domain": "example.com",
          "description": null,
          "countryCode": "US",
          "languageCode": "en",
          "publisher": "Example Media",
          "categories": [
            {
              "name": "Technology",
              "slug": "technology"
            }
          ],
          "rating": {
            "average": null,
            "count": 0
          },
          "offers": [
            {
              "id": "cm...",
              "type": "GUEST_POST",
              "price": {
                "amountCents": 25000,
                "currency": "USD"
              },
              "turnaroundDays": 7,
              "description": null
            }
          ]
        }
      ],
      "pagination": {
        "page": 1,
        "pageSize": 20,
        "total": 1,
        "totalPages": 1
      }
    }
  • GET/api/v1/marketplace/websites/{websiteId}marketplace:read

    One approved Marketplace website.

    Parameters: websiteId (path) - The website id.

    {
      "data": {
        "id": "cm...",
        "name": "Example Media",
        "domain": "example.com"
      }
    }
  • GET/api/v1/ordersorders:read

    Orders you placed, newest first, with what you paid and their invoice when issued.

    Parameters: limit (query) - 1-50, default 20.; cursor (query) - nextCursor from the previous page.

    {
      "data": [
        {
          "id": "cm...",
          "reference": "AB12CD34",
          "status": "IN_PROGRESS",
          "createdAt": "2026-01-01T00:00:00.000Z",
          "website": {
            "name": "Example Media",
            "domain": "example.com"
          },
          "offerType": "GUEST_POST",
          "amount": {
            "amountCents": 25000,
            "currency": "USD"
          },
          "paymentStatus": "CONFIRMED",
          "invoice": {
            "number": "INV-2026-00001",
            "issuedAt": "2026-01-01T00:00:00.000Z"
          }
        }
      ],
      "pagination": {
        "limit": 20,
        "nextCursor": null
      }
    }
  • GET/api/v1/orders/{orderId}orders:read

    One order you placed.

    Parameters: orderId (path) - The order id.

    {
      "data": {
        "id": "cm...",
        "reference": "AB12CD34",
        "status": "COMPLETED"
      }
    }
  • GET/api/v1/orders/{orderId}/invoiceorders:read

    The invoice issued when the order's payment was confirmed, with download links. 404 until it is issued.

    Parameters: orderId (path) - The order id.

    {
      "data": {
        "number": "INV-2026-00001",
        "issuedAt": "2026-01-01T00:00:00.000Z",
        "total": {
          "amountCents": 25000,
          "currency": "USD"
        },
        "paymentMethod": "UPI_MANUAL",
        "status": "PAID",
        "downloads": {
          "pdf": "/api/v1/orders/cm.../invoice/pdf",
          "docx": "/api/v1/orders/cm.../invoice/docx"
        }
      }
    }
  • GET/api/v1/orders/{orderId}/invoice/pdforders:read

    The invoice as a PDF file.

    Parameters: orderId (path) - The order id.

    Returns a file (application/pdf).

  • GET/api/v1/orders/{orderId}/invoice/docxorders:read

    The invoice as a Microsoft Word (.docx) file.

    Parameters: orderId (path) - The order id.

    Returns a file (application/vnd.openxmlformats-officedocument.wordprocessingml.document).

  • GET/api/v1/publisher/websiteswebsites:read

    Your websites, newest first, with their review state and your offers at your price.

    Parameters: limit (query) - 1-50, default 20.; cursor (query) - nextCursor from the previous page.

    {
      "data": [
        {
          "id": "cm...",
          "name": "Example Media",
          "domain": "example.com",
          "reviewStatus": "APPROVED",
          "publishedOnMarketplace": true,
          "offers": [
            {
              "id": "cm...",
              "type": "GUEST_POST",
              "yourPrice": {
                "amountCents": 25000,
                "currency": "USD"
              },
              "active": true,
              "turnaroundDays": 7
            }
          ]
        }
      ],
      "pagination": {
        "limit": 20,
        "nextCursor": null
      }
    }
  • GET/api/v1/publisher/orderspublisher:orders:read

    Orders placed on your websites, newest first, with what you are paid and whether they need your action.

    Parameters: limit (query) - 1-50, default 20.; cursor (query) - nextCursor from the previous page.

    {
      "data": [
        {
          "id": "cm...",
          "reference": "AB12CD34",
          "status": "REQUESTED",
          "requiresAction": true,
          "website": {
            "name": "Example Media",
            "domain": "example.com"
          },
          "offerType": "GUEST_POST",
          "yourAmount": {
            "amountCents": 25000,
            "currency": "USD"
          }
        }
      ],
      "pagination": {
        "limit": 20,
        "nextCursor": null
      }
    }

Pagination

Lists of your own records use a cursor: pass limit (1-50, default 20) and the nextCursor from the previous response as cursor. nextCursor is null on the last page.

Marketplace websites are paged like the Marketplace page: page, 20 per page, with the total.

Rate limits and versioning

120 requests per minute per API key and 240 per account across its keys; 60 per minute per address for the endpoints that need no key and for failed authentications. Over the limit, the answer is 429 with a Retry-After header.

The version is in the path. Within v1 fields are only added; anything that would break a client becomes v2.

Writes, when they come, accept an Idempotency-Key header: a retry returns the first answer instead of acting twice.

Errors

One shape for every error; every response carries X-Request-Id.

{ "error": { "code": "insufficient_scope", "message": "...", "requestId": "..." } }
  • 400 invalid_request - The request is not valid.
  • 401 unauthorized - A valid API key is required. Send it as: Authorization: Bearer <key>.
  • 403 insufficient_scope - This API key does not have the scope this endpoint needs.
  • 403 forbidden - Your account cannot use this endpoint.
  • 403 access_not_approved - This account's API access is not approved. Request access from your account's API Access page.
  • 403 scope_not_approved - This API key holds a scope your account's API access no longer allows. Create a new key.
  • 404 not_found - Not found.
  • 409 idempotency_conflict - This Idempotency-Key was already used for a different request.
  • 429 rate_limited - Too many requests. Wait, then try again.
  • 500 internal_error - Something went wrong. Try again later.

Keep keys secret

Never put an API key in a web page or a public repository. If one leaks, revoke it in your account at once and create another.