Widgets

Add a widget to a section

Writes one widget into a section of a report. The widget is defined in the widget DSL, the same vocabulary /v1/reports/get answers for the widgets it can express. Every property of the dsl schema is required, unfulfilled included: send null in the optional ones and an empty array in unfulfilled. That field belongs to the AI generator, which lists there what it could not express; a client writing the DSL itself sends an empty array. The data_view of a dsl takes its values from /v1/capabilities (the integrations block), which is not always the data_views list of /v1/integrations/detail: an integration that reads a single level when it is queried can still be drawn at several levels in a report. A refusal names the accepted values in the problem's suggestions. The integration must already have a data source in the report, and integration_id may be omitted only for a dsl whose visualization is text: a text block is prose and reads no data. A text block written into a TEMPLATE is cloned into the reports based on it, like any other widget of a template. A section holds at most 12 widgets. Without placement the widget is placed automatically. This endpoint accepts if_version and verify_data, and never asks for a confirmation, so it never answers CONFIRMATION_EXPIRED or CONFIRMATION_MISMATCH. With verify_data in a dry run the widget IS run against the provider and the verdict travels in data.verification, but the answer is still valid: true -- a rehearsal reports what it found and refuses nothing; the 422 belongs to the real write. Two callers writing into the same section at once are serialised: the second one gets 409 SECTION_BUSY with a Retry-After. An AI summary is written with ai_summary in place of the dsl, and the two are mutually exclusive: it is refused on a TEMPLATE (APPEND_NOT_ALLOWED reason template_report), it never carries a connection, and an empty widget_keys or section_keys is refused -- leave the key out to have the platform choose what it reads.

Refusals: 400 VALIDATION_FAILED (including the problem codes DSL_INVALID and TRANSLATION_FAILED), UNKNOWN_PARAM, APPEND_NOT_ALLOWED or INVALID_VALUE for a placement that does not fit, 403 WRITE_ACCESS_DISABLED, 404 NOT_FOUND, 409 VERSION_MISMATCH or SECTION_BUSY plus the idempotency conflicts, 422 WIDGET_EXECUTION_FAILED when verify_data ran the widget and the provider refused it. Creating a widget does not move the version of the report: that number covers the list of sections.

Every write endpoint reads dry_run and idempotency_key; see the Write guarantees section of the introduction.

A COMPARATOR is written with the compare block of the dsl: by accounts draws one series per connected account and names at least two of them in items, so such a widget carries no connection_key of its own -- which is also how it is written into a report that binds a connection per widget, where the items ARE the connections of the widget and a body sending the pair as well is refused with 400 INVALID_VALUE naming connection_key; by filters draws one per saved filter of the account, reads one connection like any ordinary widget and names it in the body; by breakdown splits one page metric of facebook_insights into a series per value. Only a graph_basic, a graph_pie, a graph_trend and a table_metrics_summary take one, and which classes and which axes an integration offers depends on the entity level of the data view as well as on the integration. The same account or the same saved filter named twice is refused, and a label cannot carry the sequence #%#, which is what the parts of a stored account are joined with. A comparator of connected accounts is not written into a report whose report_level_data_sources is true, which answers 409 NOT_ALLOWED with details.reason report_level_data_sources.

post/widgets/create

Request

  • Base URL: https://api.reportingninja.com/v1
  • URL: https://api.reportingninja.com/v1/widgets/create
  • Auth: HTTP bearer

Request body

report_keystring required

The report the section belongs to.

section_keystring required

The section the widget is added to.

integration_idstring

Which integration the widget reads from. The report must already have a data source for it. Required for every widget except one whose dsl has visualization: text, which reads no data: OMIT the property for a text block, do not send null. Sending a real integration there is accepted and checked the same way, and never read.

connection_keystring

The connection this widget reads through, and ONLY for a report whose report_level_data_sources is false, which binds a connection per widget: those reports refuse a widget that brings none, and a report that binds once for the whole report refuses one that brings it. Take it from /v1/connections. A widget that reads no data -- a text block, an AI summary -- takes none. An ai_summary never takes one: it reads the widgets of its report and no data source of its own.

account_idstring

The account within that connection. It travels with connection_key and is checked against the accounts /v1/connections publishes for it.

dry_runboolean

Validate and answer what WOULD happen, without writing anything. Default false.

idempotency_keystring

Makes a retry safe: the answer of the first call is replayed for 24 hours to any later call with the same key and the same body.

if_versionnumber

The version of the report's sections structure this call expects. A mismatch is HTTP 409 VERSION_MISMATCH and nothing is written.

verify_databoolean

Run the widget against the provider before writing it, waiting up to 45 seconds, and publish the verdict as data.verification. A failure verdict refuses the write with HTTP 422. Default false.

Response

The call succeeded. This endpoint reports its errors with a real HTTP status, so a 200 always carries status=ok.

status'ok' required

Changes

No recorded changes to this operation across all 1 revision of this API.