DASH:Gen

Docs

Situational dashboards — your ERP sends the rows, your colleagues open the dashboard

A situational dashboard answers one question about one thing, for a day: the sales of one customer, the lines of one invoice, the stock of one warehouse. You design it once in DASH:Gen from a sample of your data. From then on your ERP — Microsoft Dynamics NAV/Business Central, 1C, SAP, or any script — sends the current rows in one HTTP call and gets back a link. The people you named open the link, sign in, and see the dashboard drawn from exactly those rows.

1. How it works

  1. Design it. Export a sample of the data your ERP will send — a JSON array, or a CSV with the same columns — and build an HTML dashboard from it in the app, as you would any other. Change the look, the charts and the instruction until it is right — Edit dashboard opens the editor over the whole window, where you move and resize the widgets, change what each one shows, rename things and put your logo in the header. The blueprint is published from the newest version, so what you fine-tune is what the ERP's dashboards render.
  2. Publish it as a blueprint. Press Publish as blueprint beside Share. Give it a name, choose how long each drawn dashboard lives (one day by default) and how many rows a delivery may carry (at most 2 000). Publishing is free and runs no AI.
  3. Name who may open it. On the Account page, under Situational dashboards, list the e-mail addresses of the people who may open what the blueprint draws, one per line. You can always open them yourself.
  4. Wire the ERP. Make an API key on the same page. The blueprint's contract says which columns a delivery needs; your ERP sends them with the key and stores the link it gets back.

No AI runs when your ERP sends rows: the design is fixed, and the rows are drawn into it. That is why a delivery is answered in well under a second, and why it costs a fraction of a dashboard run.

Changing it later. Press Edit beside the blueprint on the Account page. The blueprint's dashboard opens in the dashboard editor, drawn on test data: rows invented from its columns — dates over two years, numbers in the range of the example, names taken from the example's values — so the editor shows no real delivery unless you ask for one. A band says so. Draw the editor on switches to the contract's example rows or to the last delivery while it is live; each switch opens the same design on those rows, free.

Change it as you would any dashboard — by hand, or with Ask the AI: drag widgets by their header, pull their edges to resize them, add, rename and delete tabs where they are, and add, duplicate and remove widgets; a click on a widget's title opens its card, where you drag the dataset's fields into the chart's wells — its measures, what it groups by, its time axis — change its type, and define calculated measures such as Cost per hour = SUM(cost) ÷ SUM(hours). See the HTML dashboard page for the editor.

Save version, then press Publish to the blueprint in the editor's band. Before it replaces anything the dialog says what the change does to the contract: the columns a delivery now has to carry — a delivery without one is drawn without the charts that need it, and refused with 422 columns-changed when no chart is left; you confirm that the ERP sends them — and the ones no chart needs any more. The blueprint takes the new design under the same id, and keeps its own columns and example: test data never becomes part of a contract. Its viewers, its key and the dashboards already drawn stay as they are; the next delivery from the ERP is drawn in the new form on the ERP's own rows, and a delivery under a reference already drawn redraws it under the same link. Only the person who published a blueprint can edit it, and an API key cannot.

2. The contract

GET /api/v1/situational/blueprints/{id}/contract answers what a delivery must contain. The Account page shows the same, with a Copy the call button. The {id} is the blueprint's id: an opened blueprint card shows it on its first line, Blueprint id, with Copy the id, and the ERP examples under How to connect your ERP already carry it.

{ "blueprint": "5d1c…", "name": "Sales by customer",
  "table": { "columns": [
      { "name": "posting_date", "type": "DATE",   "required": true },
      { "name": "customer_no",  "type": "STRING", "required": true },
      { "name": "amount",       "type": "DOUBLE", "required": true },
      { "name": "salesperson",  "type": "STRING", "required": false } ] },
  "limits": { "maxRows": 2000, "maxBodyKb": 2048 },
  "ttl": "PT24H",
  "example": [ { "posting_date": "2026-09-01", "customer_no": "C-1001", "amount": 1250.5,
                 "salesperson": "MB" } ] }

One table. A dashboard draws from one table, so the contract names one. If your data lives in a header table and a lines table — an invoice, an order — send the lines with the header's fields repeated on each of them. Your ERP loops over the lines anyway; it writes a few more fields per line. A mapping of ten tables is not one dashboard: make one blueprint per question.

3. Sending rows

curl -X PUT -H "X-Api-Key: dg_your_key" -H "Content-Type: application/json" \
  -d '{"rows":[{"posting_date":"2026-09-01","customer_no":"C-1001","amount":1250.5}],
       "title":"Müller GmbH — September"}' \
  https://dashgen.de/api/v1/situational/blueprints/5d1c…/instances/C-1001
{ "instanceId": "8f2e…", "externalRef": "C-1001", "url": "https://dashgen.de/v/8f2e…",
  "title": "Müller GmbH — September", "renderedAt": "…", "expiresAt": "…",
  "rows": 1, "chartsDropped": 0, "replaced": false, "status": "LIVE" }

Add ?format=html and the answer is the dashboard itself — one self-contained .html file — with the record in its headers instead of the JSON:

curl -X PUT -H "X-Api-Key: dg_your_key" -H "Content-Type: application/json" \
  -d '{"rows":[ … ]}' -o dashboard.html -D headers.txt \
  "https://dashgen.de/api/v1/situational/blueprints/5d1c…/instances/C-1001?format=html"
HeaderWhat it says
X-Situational-Instancethe dashboard's id
X-Situational-Refyour reference (absent for a one-off)
Content-Locationthe link a person opens, https://dashgen.de/v/{id}
X-Situational-Expires-Atwhen it stops being available, as 2026-10-16T09:00:00Z
Expires, Last-Modifiedthe same two moments as HTTP dates
X-Situational-Rows, X-Situational-Charts-Dropped, X-Situational-Replacedas in the JSON
ETagchanges exactly when the dashboard is drawn again
Cache-Controlprivate, max-age=<seconds until it expires>, must-revalidate

It costs what the JSON call costs. POST …/instances?format=html answers 201 with a Location. If the rows were drawn but the file could not be fetched, the answer is 502 file-unavailable with instanceId, externalRef, url and expiresAt — the delivery is paid and kept, so fetch it again as below.

Fetching it again is free. GET …/instances/{reference}?format=html answers the current file of that reference with the same headers, draws nothing and charges nothing. Send the ETag you got as If-None-Match and, while your copy is still the current one, the answer is 304 Not Modified with no body:

curl -H "X-Api-Key: dg_your_key" -H 'If-None-Match: "8f2e….1760600000000"' \
  -o dashboard.html -D headers.txt \
  "https://dashgen.de/api/v1/situational/blueprints/5d1c…/instances/C-1001?format=html"

An unknown reference is 404; past its lifetime it is 410 instance-expired, whatever tag you send. On a blueprint that belongs to a company the file is only for a key the company's administrator let in — see the companies page; otherwise both calls are 403 api-key-read-refused, before anything is charged.

Refusals, each before anything is charged:

AnswerWhen
413 too-many-rowsmore rows than the blueprint takes; rows and limit say how many
413 body-too-largethe request is over 2 MB
422 columns-changeda required column is missing; missingColumns names it
422 rows-invalidthe body is not {"rows": [ {…}, … ]}
422 reference-invalidthe reference has a character it may not have
409 blueprint-disabledthe blueprint is switched off on the Account page
429 instance-limittwo hundred live dashboards already; send under a reference you use, or delete one
403 api-key-scopethe key was sent to a path a key may not reach
422 format-invalidformat is neither html nor json
403 api-key-read-refused?format=html on a company blueprint its administrator has not opened to the key

4. Opening a dashboard

The link is https://dashgen.de/v/{id}. It opens a page that asks the reader to sign in, then shows the dashboard — filters, charts, cross-filtering — and when it stops being available.

Sign-in with a second factor, once a day. A company decides that for its members on its page (Password + one-time code, once a day), and the installation's sign-in service asks for the code. For readers outside a company it is a setting of the sign-in service: on dashgen.de ask us; on your own installation see the deployment guide.

5. From Navision, Business Central and 1C

The pattern is the same in every ERP:

  1. Keep two fields on the record — the customer, the document: link and valid until.
  2. When a user opens the dashboard: if valid until is still in the future, open the link. Otherwise collect the rows, send them with PUT under the record's number, store the url and expiresAt of the answer, and open the link.
  3. Open the link in the system browser, not inside an ERP form. The sign-in page, and its second factor, need a real browser; an embedded one often refuses the sign-in cookies.

Because the link of a reference never changes, step 2 can also simply send the rows every time the user asks — each send is a fresh drawing under the same link.

Showing it inside the ERP window

When the dashboard should open in the ERP's own window, with no sign-in, fetch the file instead of the link:

  1. Keep the file and its X-Situational-Expires-At (and the ETag) on the record.
  2. While it is valid, show the stored file. Otherwise send the rows with PUT …?format=html again, or — if the rows have not changed — GET …?format=html with If-None-Match, which is free.
  3. Show it from a temporary file or a string:
    • Business Central, .NET: a WebView2 control, NavigateToString(html) or a temporary .html file.
    • 1C:Enterprise 8.3.14 and later: a form's HTML document field (ПолеHTMLДокумента), its document set from a temporary file. The older field based on Internet Explorer does not run the dashboard.
    • Any current browser engine (Chromium, WebKit, Firefox) opens it, from disk as well.

The file needs no network: it loads nothing from anywhere — charts, filters and cross-filtering run inside it — so it also works offline and from file://. It keeps nothing in the browser's storage. It may tell the window around it which chart was clicked, with a postMessage of { "type": "dg:chart-selected", … }; an ERP may listen to it or ignore it.

For a company blueprint, this needs a company administrator to switch on The integration may fetch the file on the blueprint's card first — see the companies page.

6. What it costs

WhatPrice
Publishing a blueprint, changing it, naming viewersfree
One delivery through an API key0.02 Coins, with ?format=html as well
Fetching a drawn file again (GET …?format=html, 304 included)free
A delivery drawn from a file on the Account pagefree, counted among the day's free rebuilds
Opening a dashboardfree, for every reader

GET /api/v1/quota answers the current price as coins.situationalRenderCenticoins. A delivery the server refuses is given back at once. API keys come with the Pro and Max plans.

7. Your data

The rows a delivery carries are kept on the server for the dashboard's lifetime — one day unless the blueprint says otherwise, at most seven — and then deleted together with the file. A blueprint keeps the design and the column names of the sample it was published from, never its rows beyond the five example rows its contract shows. Deleting a blueprint deletes every dashboard it drew. A file your ERP fetched with ?format=html is your ERP's copy: the server deletes its own, and the Expires header says when to throw yours away. Edit is the one exception: a blueprint drawn again for editing becomes an ordinary dashboard in your list, and keeps the rows of the delivery it was drawn from for as long as any dashboard keeps its upload.