View as Markdown

Account API

Read a Reggio Digital account from your own software: websites, backups and visits, support requests, domains and DNS, invoices and plans.

The account API lets your own software read what a business has with us: its websites, their backups and visits, its support requests, its domains and DNS records, and its invoices and plans. Build a status board, pull invoices into your accounting, or let your own monitoring see when a support request is answered.

Everything on this page only reads. Nothing here can change a website, spend money or move a domain.

Getting a key

The business makes the key under API keys in their dashboard and picks what it can read. Anyone on the account can make one, but a key can never read more than the person who made it can see: support requests need access to Support, and invoices need access to Billing. The key belongs to the account, so it keeps working when that person leaves.

Ability Lets the key read
websites:read Websites, their backups and their monthly visits.
tickets:read Every support request on the account and the replies on each.
domains:read Domains, their renewal dates, and the DNS records on each zone.
billing:read Invoices, and the plans and add-ons being paid for.

A key without the ability a call needs gets a 403 with forbidden. Call GET /me to see what a key has.

An account that has not bought anything yet still gets answers. Its lists are simply empty.

Lists and pages

Every list comes back in the same shape, newest first:

{
  "data": [],
  "has_more": true,
  "next_cursor": "eyJpZCI6MTE4LCJfcG9pbnRzVG9OZXh0SXRlbXMiOnRydWV9"
}
  • limit sets how many come back, from 1 to 100. The default is 25.
  • When has_more is true, ask again with cursor set to the next_cursor you were given, exactly as it came. When it is false, you have everything and next_cursor is null.
  • A cursor rather than a page number means a record added while you are paging never shows up twice.

A limit out of range, or a cursor we did not give you, gets a 422 with invalid_request.

An id that is not on this account, or belongs to another account, gets a 404 with not_found. We never say whether it exists somewhere else.

Websites

Needs websites:read.

Listing websites

GET /api/v1/websites

curl https://reggiodigital.com/api/v1/websites?limit=25 \
  -H "Authorization: Bearer $REGGIO_API_KEY"
{
  "data": [
    {
      "id": 118,
      "name": "Glass Jug Beer Lab",
      "url": "https://glassjugbeer.com",
      "status": "active",
      "is_staging": false,
      "staging_of": null,
      "hosting": "reggio",
      "wordpress_version": "6.8.2",
      "php_version": "8.3",
      "uptime": {
        "status": "up",
        "checked_at": "2026-09-25T13:55:00+00:00",
        "changed_at": "2026-09-02T04:10:00+00:00"
      },
      "created_at": "2025-03-14T16:20:00+00:00"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
  • status is active, suspended or maintenance.
  • hosting is reggio when we host it, pressable for a site still on our previous host, and external for a site hosted somewhere else that we look after.
  • A staging copy has is_staging set and staging_of holding the id of the live site it was copied from.
  • uptime.status is up, down or unknown until we have checked it.

One website

GET /api/v1/websites/{id}

curl https://reggiodigital.com/api/v1/websites/118 \
  -H "Authorization: Bearer $REGGIO_API_KEY"

Answers with one website in the shape above, on its own rather than inside data.

Backups

GET /api/v1/websites/{id}/backups

curl https://reggiodigital.com/api/v1/websites/118/backups \
  -H "Authorization: Bearer $REGGIO_API_KEY"
{
  "data": [
    {
      "id": "a1b2c3d4",
      "type": "full",
      "status": "completed",
      "created_at": "2026-09-25T05:30:00+00:00"
    }
  ],
  "has_more": false,
  "next_cursor": null
}

The restore points the dashboard lists, up to the latest 50, newest first. Downloading or restoring a backup stays in the dashboard. A site hosted somewhere else has none.

Visits

GET /api/v1/websites/{id}/traffic

curl https://reggiodigital.com/api/v1/websites/118/traffic \
  -H "Authorization: Bearer $REGGIO_API_KEY"
{
  "data": [
    { "month": "2026-08", "visits": 18240, "storage_mb": 2140 },
    { "month": "2026-09", "visits": 15321, "storage_mb": 2188 }
  ],
  "has_more": false,
  "next_cursor": null
}

Twelve months, oldest first, ending with the current billing month. These are the figures on the website's page in the dashboard. storage_mb is the latest reading in that month, or null when we have none.

Support requests

Needs tickets:read.

Listing support requests

GET /api/v1/tickets

curl https://reggiodigital.com/api/v1/tickets?status=open \
  -H "Authorization: Bearer $REGGIO_API_KEY"
{
  "data": [
    {
      "id": 2051,
      "title": "Contact form stopped sending",
      "description": "Nothing has arrived from the contact page since Tuesday.",
      "status": "open",
      "priority": "high",
      "category": "support",
      "website_id": 118,
      "opened_by": "Sam Rivera",
      "created_at": "2026-09-24T14:02:00+00:00",
      "updated_at": "2026-09-25T09:12:00+00:00"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
  • Add status to see only open, pending or closed requests.
  • priority is low, medium, high or urgent.
  • website_id is null when the request is about the account rather than one site.

GET /api/v1/tickets/{id} answers with one request in the same shape.

Replies

GET /api/v1/tickets/{id}/comments

curl https://reggiodigital.com/api/v1/tickets/2051/comments \
  -H "Authorization: Bearer $REGGIO_API_KEY"
{
  "data": [
    {
      "id": 88412,
      "author": "Jordan at Reggio Digital",
      "body": "Found it. The form was sending from an address that is no longer set up. It is fixed and the missed messages have been resent.",
      "created_at": "2026-09-25T09:12:00+00:00"
    }
  ],
  "has_more": false,
  "next_cursor": null
}

Newest first. Attachments stay in the dashboard for now.

Domains and DNS

Needs domains:read.

Domains

GET /api/v1/domains

curl https://reggiodigital.com/api/v1/domains \
  -H "Authorization: Bearer $REGGIO_API_KEY"
{
  "data": [
    {
      "id": 64,
      "domain": "glassjugbeer.com",
      "status": "active",
      "registered_at": "2019-05-02T00:00:00+00:00",
      "expires_at": "2027-05-02T00:00:00+00:00",
      "auto_renew": true,
      "locked": true,
      "nameservers": ["ada.ns.cloudflare.com", "rob.ns.cloudflare.com"],
      "website_id": 118
    }
  ],
  "has_more": false,
  "next_cursor": null
}

The domains registered or transferred to us. GET /api/v1/domains/{id} answers with one. A transfer code is never available here; request one from the domain's page in the dashboard.

DNS zones and records

GET /api/v1/dns-zones lists the zones we run DNS for, and GET /api/v1/dns-zones/{id} answers with one:

{
  "id": 37,
  "name": "glassjugbeer.com",
  "status": "active",
  "paused": false,
  "name_servers": ["ada.ns.cloudflare.com", "rob.ns.cloudflare.com"],
  "records": 14,
  "activated_at": "2024-01-18T10:00:00+00:00"
}

GET /api/v1/dns-zones/{id}/records lists the records on a zone:

curl https://reggiodigital.com/api/v1/dns-zones/37/records \
  -H "Authorization: Bearer $REGGIO_API_KEY"
{
  "data": [
    {
      "id": 5120,
      "type": "A",
      "name": "glassjugbeer.com",
      "content": "203.0.113.10",
      "ttl": 1,
      "priority": null,
      "proxied": true
    }
  ],
  "has_more": false,
  "next_cursor": null
}

A ttl of 1 means automatic. priority is set on MX and SRV records only.

Billing

Needs billing:read.

Invoices

GET /api/v1/invoices

curl https://reggiodigital.com/api/v1/invoices \
  -H "Authorization: Bearer $REGGIO_API_KEY"
{
  "data": [
    {
      "id": 9031,
      "number": "RD-2026-0412",
      "status": "paid",
      "currency": "USD",
      "subtotal": "95.00",
      "tax": "0.00",
      "discount": "0.00",
      "total": "95.00",
      "amount_paid": "95.00",
      "amount_due": "0.00",
      "description": "Monthly plan",
      "period_start": "2026-09-01T00:00:00+00:00",
      "period_end": "2026-10-01T00:00:00+00:00",
      "due_date": "2026-09-01T00:00:00+00:00",
      "paid_at": "2026-09-01T06:02:00+00:00",
      "created_at": "2026-09-01T06:00:00+00:00"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
  • Amounts are strings with two decimal places, in the invoice's currency, so nothing is lost to rounding.
  • status is draft, open, paid, void or uncollectible.
  • GET /api/v1/invoices/{id} answers with one. The PDF stays in the dashboard for now.

Plans and add-ons

GET /api/v1/subscriptions

curl https://reggiodigital.com/api/v1/subscriptions \
  -H "Authorization: Bearer $REGGIO_API_KEY"
{
  "data": [
    {
      "id": 412,
      "label": "Business Hosting (Plan #412)",
      "status": "active",
      "is_plan": true,
      "items": [
        { "name": "Business Hosting", "quantity": 1, "price": "95.00", "interval": "month" },
        { "name": "Transactional Email", "quantity": 1, "price": "15.00", "interval": "month" }
      ],
      "sites": 3,
      "site_limit": 5,
      "trial_ends_at": null,
      "ends_at": null
    }
  ],
  "has_more": false,
  "next_cursor": null
}

Everything the account is paying for, the same as the billing page. An account can have more than one plan, so read every entry rather than the first. is_plan is false for a subscription that only holds add-ons such as email, and sites and site_limit only mean something when it is true. ends_at is set when a plan has been cancelled and is running to the end of what was paid for.