NextSign API
Cases

List Cases

Page through your company's cases with GET /v3/api/cases — filters, cursor pagination and the response shape.

Returns your company's cases, newest first, one page at a time.

GET https://api.nextsign.dk/v3/api/cases

Authenticated with an API key — see Authorization.

Quickstart

curl "https://api.nextsign.dk/v3/api/cases?limit=25&state=open" \
  -H "Authorization: Bearer $NEXTSIGN_API_KEY"
const params = new URLSearchParams({ limit: '25', state: 'open' });

const response = await fetch(`https://api.nextsign.dk/v3/api/cases?${params}`, {
  headers: { Authorization: `Bearer ${process.env.NEXTSIGN_API_KEY}` },
});

const { cases, nextCursor, hasMore } = await response.json();
import os, requests

response = requests.get(
    "https://api.nextsign.dk/v3/api/cases",
    headers={"Authorization": f"Bearer {os.environ['NEXTSIGN_API_KEY']}"},
    params={"limit": 25, "state": "open"},
)

page = response.json()

Query Parameters

ParameterTypeDefaultDescription
limitinteger25Cases per page, 1–100
cursorstringWhere to continue from. Use nextCursor from the previous page
statestringallOne of draft, open, completed, denied, cancelled
referenceIdstringallExact match on your own identifier. Not a search
folderstringallExact folder name
createdAfterstringISO 8601. Cases created at or after this moment
createdBeforestringISO 8601. Cases created at or before this moment
includeDeletedbooleanfalseInclude cases moved to the bin
publicUrlsbooleanfalseReturn downloadable document links. See Document URLs

Anything else is rejected. A misspelled parameter returns 400 validation-failed naming it, rather than silently returning unfiltered results — a filter that is quietly ignored is the one mistake you cannot see in the response.

400 Bad Request
{
  "error": "validation-failed",
  "details": [{ "field": "page", "message": "unknown field" }]
}

Dates must be ISO 86012026-01-31 or 2026-01-31T09:00:00Z. A bare year like 2026 is rejected rather than quietly read as January 1st.


Pagination

Paging is by cursor, not page number. Each response carries a nextCursor; pass it back to get the next page, and stop when hasMore is false.

let cursor = null;
const all = [];

do {
  const params = new URLSearchParams({ limit: '100' });
  if (cursor) params.set('cursor', cursor);

  const response = await fetch(`https://api.nextsign.dk/v3/api/cases?${params}`, {
    headers: { Authorization: `Bearer ${process.env.NEXTSIGN_API_KEY}` },
  });

  const page = await response.json();
  all.push(...page.cases);
  cursor = page.nextCursor;
} while (cursor);

Two things follow from this that page numbers would not give you:

  • New cases do not shift your pages. A cursor marks a position in the results, not an offset, so a case created while you are paging cannot push a row onto a page you have already read — with ?page= it would, and you would see the same case twice.
  • The last page costs what the first one did. Every page is a bounded lookup rather than a count-and-skip, so paging deep into a long history does not get slower.

Treat the cursor as opaque. It is a position marker whose format is ours to change — do not parse it, build one, or store one long-term. A cursor you did not receive from us returns 400 validation-failed on the cursor field.

There is no total. Counting every case in a company is the one query that would make deep paging expensive again, so we do not run it on your behalf. If you need a count, page with limit=100 and add up what you receive.


Document URLs

By default documents[].url is the document's stored address. It identifies the file and is stable, but it is protected — fetching it without credentials returns 403.

Pass ?publicUrls=true to get downloadable links instead:

curl "https://api.nextsign.dk/v3/api/cases?publicUrls=true" \
  -H "Authorization: Bearer $NEXTSIGN_API_KEY"
{ "url": "https://nextsign-de.fsn1.your-objectstorage.com/65ab/contract.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Expires=3600&X-Amz-Signature=fa2ca5b25…" }

These expire after an hour, which is why they are opt-in: minting one for every document on every page — when most callers are checking who has signed — produces links that are stale before anyone clicks them. Ask for them on the page where you intend to download.

Documents you supplied as a url are returned exactly as you gave them, with or without this parameter. We store those by reference and never re-host them — which is also why their type is null, since we never fetched the bytes to inspect.


Response

200 OK
{
  "cases": [
    {
      "id": "65ab12cd34ef56ab78cd90b0",
      "referenceId": "Jrn. 2342-23",
      "title": "Lejeaftale",
      "state": "open",
      "language": "da",
      "createdAt": "2026-07-27T14:48:36.356Z",
      "expiresAt": "2026-08-10T14:48:36.356Z",
      "folder": { "id": "65ab12cd34ef56ab78cd90a2", "name": "Default" },
      "sender": {
        "id": "65ab12cd34ef56ab78cd90ef",
        "name": "Anna Beck",
        "email": "anna@example.com"
      },
      "activeGroup": 0,
      "recipients": [
        {
          "id": "65ab12cd34ef56ab78cd91a1",
          "uid": "4t5ZQbtB",
          "name": "Andreas Lauridsen",
          "email": "al@example.com",
          "phone": "",
          "position": "",
          "group": 0,
          "type": "email",
          "signing": true,
          "status": "signed",
          "needsCpr": false,
          "signingSchema": ""
        }
      ],
      "documents": [
        {
          "id": "65ab12cd34ef56ab78cd92c3",
          "name": "contract.pdf",
          "type": "application/pdf",
          "url": "https://nextsign-de.fsn1.your-objectstorage.com/65ab/contract.pdf",
          "signObligated": true,
          "documentMustBeRead": false,
          "signatories": []
        }
      ],
      "notices": []
    }
  ],
  "nextCursor": "MTc4NTI0NDYwNjU5OS42NWFiMTJjZDM0ZWY1NmFiNzhjZDkwYjA",
  "hasMore": true
}

Each entry is the same case object Create a Case returns, so anything you already parse from a creation response works here unchanged.

FieldDescription
casesThis page of cases, newest first
nextCursorPass as ?cursor= for the next page. null on the last page
hasMoreWhether another page exists. Equivalent to nextCursor !== null

Two fields from the creation response are absent here, both because they describe an event rather than the case:

  • delivery reports the outcome of sending, which happened once, at creation.
  • recipients[].signingUrl is not returned by the list. Signing links contain the credential that authenticates a signing session, and a list is what integrations put on a schedule — one such request should not be able to collect every open case's signing link. Fetch the case with Retrieve a Case when you need them.

notices is present and always empty. It records what we filled in for you while creating a case; nothing is being filled in here.


What you see

An API key belongs to a company, and this endpoint returns that company's cases — all of them, regardless of which colleague created each one or which folder it sits in. Folder permissions govern what a person sees when they log in; they do not narrow what a key can read.


Errors

errorStatusMeaning
validation-failed400A query parameter is invalid or unrecognised. See details

Reading never changes anything, so every request here is safe to retry. Full detail in Errors.