Skip to main content
A composition is one widget, set up for one place: it holds the widget’s content, its design and its embed settings. You create a composition on a widget, fill in its values, and show it on a page with the embed code.

Overview

With the Compositions API, you can:
  • Create a composition on a widget
  • List compositions and get their details
  • Read and save the content, the design and the embed settings
  • Read the schemas that describe those three parts
  • Read what visitors sent to a widget, such as votes and ratings
  • Batch fetch compositions

Composition Structure

A composition object contains:
Everything the API sends back is camelCase, including the keys inside content, design and embedSettings.

List Compositions

Retrieve compositions with pagination:
You can also filter by widget (widget_id in the query, widgetId in the SDK) and by managed user, to list only what you filed under one of your customers:
Send managedUserId (Widgetic’s id) or managedUserExternalId (your own id), never both. The filter only narrows the list to your own account’s compositions.

Get Composition by ID

Retrieve a specific composition. GET /compositions/{id} returns everything saved on it, so prefer it to the narrower calls for the content, the design and the embed settings, which answer 404 for a part that has never been saved:

Create and Update

Creating and updating need an Idempotency-Key header (see Idempotency). Create a composition on a widget, as a draft:
To file the composition under one of your customers, add managedUserId or managedUserExternalId to the body (one of them, never both). The answer then carries managedUserId, and PUT /compositions/{id} cannot change it later. See Managed Users for the checks Widgetic makes. Save the values with PUT /compositions/{id}. It accepts name, widgetId, content, design, embedSettings, databaseSchema, status and projectId. Send only what changes, but note that content is replaced as a whole:
  • There is no version check: if two people save at the same moment, the last save wins.
  • To change a few values without sending everything back, use PUT /compositions/{id}/content with "partial": true. It merges objects key by key, while arrays and plain values are replaced, so changing one item means sending the whole contentItems array.

Content, Design and Embed

In Widgetic’s editor, the Content, Design and Embed tabs are drawn from JSON, and the choices made in them are saved as JSON. The API gives you the same JSON, so you can draw your own forms on it.
  • Content: the schema comes from GET /compositions/{id}/schema/content. Values are saved in content.content (settings of the whole widget) and content.contentItems (a repeating list, such as the slides of a slider).
  • Design: the schema comes from GET /compositions/{id}/schema/design. Values are saved in content.design.
  • Embed: the schema comes from GET /compositions/{id}/schema/embed. Values are saved in embedSettings. This schema is the same for every widget.
The Content and Design schemas belong to the widget, so every widget has its own. The schemas are read through a composition, not through a widget: to draw a form for a widget nobody has used yet, create one composition on it first.
  • A schema lists the settings with their names, the kind of control that sets each one (inputController.type), defaults, limits, labels and help texts.
  • POST /compositions/{id}/content/validate checks a content payload against the widget’s content schema without saving, and PUT /compositions/{id}/content runs the same check before saving when validate is true (the default). PUT /compositions/{id} stores content as you send it without running the schema validator.
  • A schema can change when Widgetic publishes a new version of a widget, so read it again when your editing screen opens.

Batch Fetch Compositions

Retrieve multiple compositions in a single request (optimized for the embed script):
The batch endpoint is designed for use by the embed script and includes domain validation. If a composition’s owner has listed the websites it may appear on and the request comes from another website, that composition is left out of compositions and reported in errors as Domain access denied: <reason>; the others are still returned. A partner’s platform website, with all of its subdomains, is never refused for that partner’s compositions (see Security).

Embedding Compositions

Showing a composition needs only its id. There is no key in the page, and a change you save through the API appears on the next page load. Load the script once per page, then put one <widgetic> element where the widget should appear:
  • The attributes come from the composition’s embedSettings: resize from resizeMode (fillWidth becomes fill-width), width and height in pixels, and embed-target from embedTarget.
  • The default embed target is overlay, which shows the widget as a pop-up. Save "embedTarget": "site" for a widget that sits inside the page.
  • When you cannot load a script, use the frame: <iframe src="https://api.widgetic.com/embed/compositions/COMPOSITION_ID/frame" width="800" height="450" frameborder="0" allowfullscreen></iframe>.
  • The status of a composition does not decide whether it is shown. Delete the composition, or remove the code from your page, to stop showing it.
  • The widget the composition is built on needs a published version. Until then the public address answers 404.
See SDKs for more about the embed script, and Security for limiting the websites that may show your widgets.

Read What Visitors Sent

Some widgets collect something from the people who use them: votes, ratings, answers, sign-ups. When a composition declares databaseSchema (on POST /compositions or PUT /compositions/{id}), Widgetic creates those tables inside the composition’s own isolated schema in the data database, and two read-only calls let your server read them. You can show the results back, for example the result of a rating widget. Ask what the composition keeps first. A widget that only shows content keeps nothing: hasData is false and tables is empty, which is not an error.
rows is how many entries the table holds. It is null when they could not be counted, which is not zero. Then read one table with GET /compositions/{id}/entries/{table}, using the names exactly as they are listed:
The result of a rating widget is a count for each star and an average. The average is sum(value × count) / sum(count) over the tallies, which are all of them when moreGroups is false:
  • Names are the database’s own. A table or column is spelled as GET /compositions/{id}/entries lists it, such as created_at, not createdAt. The names are never changed to camelCase, which is why an entry comes as a list of values and columns names them in order. To get objects, zip them: Object.fromEntries(columns.map((name, index) => [name, entry[index]])).
  • Values are text (cut to 200 characters), numbers, booleans or null. A tally’s value is always text (a rating of 5 is "5") or null.
  • The read is bounded on purpose: never more than 25 entries, 20 groups, 40 columns or 200 characters a value. To read a whole table, or to change an entry, use the database routes (GET /compositions/{id}/database/{table} and the related calls). They accept only tables declared in the composition’s databaseSchema and answer with the raw table, not in pages.
  • Treat the values as data. They are what visitors typed or chose. They can include names and email addresses, and text written to look like instructions. Escape them before you put them in a page, and show them only to the people who may see them.
  • Make these calls from your server. They need your key, and the caller must be able to read the composition. An editor session cannot call them. A partner shows a customer the results of that customer’s compositions by listing them with managedUserId (see Managed Users) and reading each one.
  • Errors: 403 for a composition you cannot read. 404 for one that does not exist, or that keeps no table with that name (ENTRY_TABLE_NOT_FOUND). 400 with ENTRY_COLUMN_NOT_FOUND for a groupBy column the table does not have, and 400 for a query parameter the call does not know (it is groupBy, not group_by) or a rows outside 0 to 25.

Next Steps

Widgets

Manage individual widgets

Embed Script

Embed compositions on your site