Skip to main content
A managed user is a record in your partner registry, one for each of your platform’s customers. It is not a login, and it does not own anything. Everything you create through the API still belongs to your administering account. What you can do is file a composition, a widget or an upload under a managed user when you create it, and later list only what one customer made, so your customers never see each other’s work. A workflow that a customer makes in their own editor session, or that you make with your key and the customer’s header, is filed under them by itself.

Overview

A managed user is:
  • A record with a Widgetic id (a UUID), your own externalId (unique among your managed users, for example your customer number), a free-form metadata object and an isActive switch.
  • Visible only to you. A record that belongs to another partner answers 404, never 403, so nothing about other partners can be learned.
  • A label you can put on compositions, widgets and uploads, to list them by customer. See Filing Content Under a Managed User. A customer’s editor session, and your key with the customer’s header, put the same label on the workflows they make.
A managed user is not:
  • A login. It has no password and no API key, and you cannot sign in as a managed user. The one thing that acts for a managed user is an editor session: a short-lived token your server makes, so that the customer’s browser can use Widgetic’s editors on what is filed under them and nothing else.
  • An owner. Compositions, widgets, uploads, workflows, credits, storage and the list of allowed websites belong to your administering account, and an unscoped call with your key can read, change and delete all of them. To restrict a composition or workflow call made with your server key so it reaches only one customer’s, send X-Managed-User-Id or X-Managed-User-External-Id on the request (see Scoping a Composition Call to One Customer and Scoping a Workflow Call to One Customer), or mint an editor session for the customer’s browser.
  • A billing unit. There are no per-customer credits, storage or invoices. You are invoiced once, for the contract. What a customer’s editor sessions spent on the AI can be read per customer, so you can bill them for it yourself (see What a Managed User Spent). See Credits & Billing.
The examples on this page are for your server. Keep the key in an environment variable, such as WIDGETIC_PARTNER_KEY.

Creating Managed Users

Create a managed user for each of your platform’s customers. Send the Idempotency-Key header, and note that this request body uses snake_case while answers use camelCase:
  • 201 on success. 409 if you already have a managed user with that external_id. 400 if external_id is missing.
  • manager_id is optional and defaults to you. Leave it out: you can only use your own, and another account’s id is refused with 403.
  • Use camelCase keys inside metadata. The API converts every key in every answer to camelCase, so company_name would come back as companyName.
POST /managed-users and PUT /managed-users/{id} need an Idempotency-Key header (see Idempotency). In the @widgetic/api-sdk-ts package, send it as idempotencyKey in the request object of createManagedUser and updateManagedUser, and send the same one when you retry.

Listing Managed Users

GET /managed-users returns your managed users, newest first. The query takes page, size (at most 100) and sort (default created_at:desc). The answer has data, a list, and meta with page, size and total:

Getting a Specific User

GET /managed-users/{id} returns one record:
There is no search by external_id in GET /managed-users. You do not need one to file or list a customer’s work: the calls below accept your own id for the customer (managedUserExternalId) and look the managed user up for you.

Filing Content Under a Managed User

When you create a composition, a widget or an upload for one of your customers, name the managed user in the request. Widgetic records it on the new item, and you can list only that customer’s items afterwards. Name the managed user in one of two ways. Send one, never both (400): Both are optional. A request that names no managed user creates an item that belongs to your account alone, exactly as before. An empty value (null or "") counts as naming no one.

Compositions and widgets

Add the field to the body of POST /compositions or POST /widgets:
The answer carries managedUserId, Widgetic’s id for the customer, or null for an item that belongs to your account alone. To list one customer’s items, send the same field in the query of GET /compositions or GET /widgets:
The filter only narrows the list: you still get nothing but your own account’s items, and it combines with the paging and the other filters of the call (widget_id on compositions, canvasId on widgets). Spell the two fields exactly as shown, in camelCase: managed_user_id on these calls is refused with a 400, not ignored, so a mistyped filter can never hand you every customer’s items.

Uploads

POST /uploads is a multipart form, so its fields are snake_case like the rest of that call: send managed_user_id or managed_user_external_id as a form field next to file. GET /uploads takes the same two names in its query, and every upload in an answer says managed_user_id (null when there is none).
Your uploads with an API key are kept in your own storage, which is required: without it POST /uploads is refused with 409 PARTNER_STORAGE_REQUIRED. A file that came through a customer’s editor session is filed under that customer by itself. A resumable upload (POST /uploads/tus, which needs a signed-in session, not an API key) files a file the same way, and it keeps it in your own storage too: without one the upload is refused when it is declared. Put managed_user_id or managed_user_external_id in its Upload-Metadata, never both. The managed user is checked when the upload is declared, so a wrong one is refused before any byte is sent, and again when the file is stored. The finished file carries managedUserId, is found with the managed_user_id filter of GET /uploads, and is counted for that customer in the storage report.

What Widgetic checks

  • The managed user must be one of yours. One that does not exist, and one that belongs to another partner, get the same answer, 404 with the code MANAGED_USER_NOT_FOUND, so nothing about other partners can be learned. Nothing is created or listed.
  • A managed user that has been switched off (see Updating) cannot be given anything new: 409 MANAGED_USER_INACTIVE. Its existing items stay and can still be listed.
  • A value that is not a UUID (for managedUserId), is not text, or is longer than 255 characters (for managedUserExternalId) is refused with 400 MANAGED_USER_REFERENCE_INVALID. So is a field spelled the other way (managed_user_id where the call reads managedUserId, or managedUserId on /uploads): it is refused, never ignored, so an item is never filed under no one, and a list is never unfiltered, without you knowing. Sending both fields is 400 MANAGED_USER_REFERENCE_AMBIGUOUS.
  • The label is set when the item is created, from your request only, and a PUT or PATCH does not change it. There is no way yet to move an item to another managed user or to take the label off (see Not Available Yet).
  • A copy of a composition that you duplicate is filed under the same managed user as the original.
  • A workflow is filed under a managed user when a customer’s editor session makes it, or when you make it with your key and the customer’s header (see Scoping a Workflow Call to One Customer), and in no other way. A workflow you make or copy without the header is your account’s own, not the customer’s.
Filing under a managed user does not change who owns the item: the item belongs to your account and the credits it spends are your account’s. What filing decides is what an editor session for that managed user can open, and what a server call carrying X-Managed-User-Id or X-Managed-User-External-Id may reach.

Scoping a Composition Call to One Customer

When your backend handles a composition request on behalf of one signed-in customer, send X-Managed-User-Id (Widgetic’s UUID for the managed user) or X-Managed-User-External-Id (your own external_id for the customer) on the call—one of the two, never both:
In @widgetic/api-sdk-ts, pass xManagedUserId or xManagedUserExternalId in the request object (or set the header once on new Configuration({ accessToken, headers: { 'X-Managed-User-External-Id': 'your-platform-user-123' } }) for a per-request client):
  • GET /compositions lists only that customer’s compositions, and POST /compositions files the new composition under that customer.
  • Any call to /compositions/{id} or its sub-routes (content, design, entries, database records, duplicate, publish, delete) succeeds only if the composition is filed under that customer; another customer’s composition or an unfiled composition returns 404.
  • Calling an account-wide route with either header returns 403 MANAGED_USER_SCOPE_ROUTE_NOT_AVAILABLE, and an empty or malformed header returns 400 MANAGED_USER_SCOPE_INVALID.

Scoping a Workflow Call to One Customer

The same two headers work on the calls of Workflows, which are made in your own workspace, written as the word personal:
  • GET /workspaces/personal/workflows lists only that customer’s workflows, and POST /workspaces/personal/workflows files the new workflow under that customer, as does duplicating one of theirs.
  • Any call on /workspaces/personal/workflows/{workflowId} or its sub-routes (save, delete, publish, discard, versions, restore, pause, resume, archive, unarchive, counts) succeeds only if the workflow is filed under that customer. Another customer’s workflow, one you made without a header, another account’s and one that does not exist all return 404 RESOURCE_WORKFLOW_NOT_FOUND.
  • A workspace other than personal, such as the id of an organization, returns 403 MANAGED_USER_SCOPE_ROUTE_NOT_AVAILABLE.
  • A customer you switched off keeps its workflows and you can still read and change them, but making or copying one for it returns 409 MANAGED_USER_INACTIVE.

Preset Widgets

A preset is a widget of your own that you offer your customers as a ready-made starting point: a rating, a quiz, a poll. You choose which of your widgets are presets and give each one a short key that your code uses. Your server reads the list, your page draws its own picker, and your server makes what the customer picked. A workflow of yours can be offered as a starting point too, as long as every widget it chains is one of these presets: see Starting points.
These are your presets, kept in your account. They are not the starter widgets that Widgetic puts on every new Widgetic account when it is made. Those belong to Widgetic and are copied at sign-up.

Register a preset

A preset is one of the widgets your own account owns: one you made in the dashboard or with the widget creator. The widget ids Widgetic gives you for compositions are not yours, so they cannot be presets. Send PUT /partners/{partnerId}/presets/{key}:
Sending the same key again replaces the preset, so the call is safe to repeat and needs no Idempotency-Key. It replaces the whole preset: a title, description or position you leave out goes back to its default. A widget can be a preset under one key only, and an account can have 100 presets. DELETE /partners/{partnerId}/presets/{key} takes a widget off the list and answers { "removed": true }, or false (not an error) when there was no such preset. It leaves the widget, its copies and its compositions alone. Deleting the widget removes its preset. A workflow you offer as a starting point can chain only widgets that are presets, so taking a widget off the list makes the starting points that chain it unavailable until you offer the widget again (unavailableReason is widget_not_preset).

List the presets

GET /partners/{partnerId}/presets returns your presets, ordered by position and then by key. It is the same list for every customer, so call it from your server whenever your picker opens.

Make what the customer picked

There are two ways. The first needs no copy.
  • A composition, for the composition editor. Create it on the preset’s widget with POST /compositions, naming the customer as in Filing Content Under a Managed User. The widget stays yours and the composition is the customer’s own content. The widget needs a published version before the composition can be shown on a page.
  • A copy to build on, for the widget creator. POST /managed-users/{id}/presets/{key}/copy gives the customer a widget of their own on a new canvas, filed under them. It needs an Idempotency-Key. The optional name (up to 120 characters) names the copy; without it the copy takes the preset’s title, then the widget’s own name. If you mount the widget creator in your page, you do not need to make this call yourself: the creator offers your presets to a customer who has made nothing yet and makes the copy for them (see Offer your presets to a new customer). Make it yourself when you draw your own picker, and give the copy’s canvasId and widgetId to the creator.
Mount the widget creator on that canvasId and widgetId, with the customer’s editor session. What a copy is:
  • It is a draft widget in your account, filed under that customer, and no other customer’s editor can reach it.
  • It carries the preset’s code, its Content and Design schemas, its content and its thumbnail, and it starts from a fork of the code, so the customer’s chat edits begin where yours left off. It does not carry the preset’s database, its compositions or its chat history. It is private and a draft, and it is not a preset itself.
  • There is no limit on copies. A customer can have as many copies of a preset as you give them, and each one is its own draft. Call again with a new Idempotency-Key for another copy; the same key gives you the first answer back.
  • A change you make to a preset’s widget later reaches the compositions you make from it and the copies you make afterwards. Copies made earlier are not touched.
  • Read warnings. When the preset’s code could not be forked, the copy opens as a preview and its code history starts empty, and warnings says so.
An editor session cannot call any of these routes. They are for your server, so what a customer is offered is decided there.

Updating Managed Users

PUT /managed-users/{id} changes the external_id, the metadata and/or is_active. It needs an Idempotency-Key. The metadata is replaced as a whole, so send all of it:
To stop a customer from creating anything new, for example when their plan on your platform ends, switch their managed user off. Send a real true or false, not text:
What the managed user already has stays, and can still be listed. Switching a managed user off also ends all of its editor sessions, and they do not come back when you switch it on again: make new ones. Send "is_active": true to switch it back on.

Deleting Managed Users

DELETE /managed-users/{id} removes the record and answers 200 with {"message": "...", "id": "..."}. It does not delete anything else, but it does remove the label: the compositions, widgets, uploads and workflows that were filed under the managed user stay in your account, with managedUserId back to null. Its editor sessions end. So when a customer leaves, list their items first (GET /compositions?managedUserId=...), delete what you want gone (DELETE /compositions/{id}), and only then delete the managed user. A customer’s workflows stay too, and keep running on every page that shows them. Pause or delete the ones that should stop before you delete the managed user: a session made for that customer, or your key with their header, lists theirs, and your own sign-in lists every customer’s (see Workflows).

Managed User Entitlements

Entitlements are read only: Widgetic sets them and you cannot change them through the API.
  • GET /entitlements/managed-users/{managedUserId} lists the entitlements of one managed user. The answer has data.managedUserId and data.entitlements.
  • GET /entitlements/partners/{partnerId} lists what your partner record is entitled to.
  • Both accept feature, source and includeExpired as filters.
  • Each entitlement has a feature, a value, a source (subscription, contract, manual, marketplace or addon) and expiresAt.

What a Managed User Spent

Your account pays for the AI, so your credit ledger does not say which customer used what. For what a customer does in an editor session, Widgetic keeps a note of each call that took credits, and adds the notes up for one customer over a period:
The answer has the credits in total and for each operation, with the generations that were refunded counted apart. It covers what editor sessions spent, from the day Widgetic first recorded it; what you spend with your own key is not in it. The period, the answer and the limit you can put on a single session are on Editor Sessions.

What a Managed User Keeps

The files a customer keeps are counted for them too. GET /partners/{partnerId}/storage/usage says how many files and how many bytes each of your managed users has, split into what is in your own storage and what is with Widgetic, with the heaviest first. A file counts for a customer when it was filed under them (an upload that names the managed user, or one that came through their editor session). The answer is counted when you ask, so it is always current. See What Each Customer Keeps for the answer and an example.

Keep Your Own Mapping

Widgetic records which managed user a composition, a widget or an upload was filed under, but it does not know your customers’ permissions: which of them may open which composition is decided by your platform. Keep a small mapping of your own, and use the filter for listing:
  • A customers table: your customer id, and the Widgetic managed-user id.
  • A widgets table (optional): your customer id, the Widgetic composition id, and the Widgetic widgetId it is built on. Handy when you show a customer a page of their compositions without calling Widgetic, and when you decide who may open one.
  • Put the customer in the composition name as well, for example your-platform-user-123 / homepage slider, so a person looking in the Widgetic dashboard can tell whose it is.

User Metadata Schema

The metadata field is flexible, but we recommend including:
Widgetic stores this object and gives it back. It does not act on it: a role here does not change what anyone can do in Widgetic.

Best Practices

Use your platform’s user ID as the external_id for easy correlation:
When a user leaves your platform, list their compositions with managedUserId, delete what you want gone, then delete their managed user. Deleting a managed user does not delete anything else, but the items that were filed under it lose the label and become your account’s own. That includes the customer’s workflows, which keep running until you pause or delete them.
List a customer’s items with managedUserId or managedUserExternalId on every call, from your own backend. A call without the filter lists everything on your account, for every customer.

Not Available Yet

  • Signing in as, or getting a key for, a managed user. A managed user’s browser can use Widgetic’s editors with an editor session, and nothing more.
  • Moving a composition, a widget or an upload to another managed user, or taking its label off, after it was created. The same holds for a workflow.
  • A charge for storage per customer. What each customer keeps is counted (see What a Managed User Keeps), and what you charge for it is yours to decide. The credits an editor session spends are noted for its customer (see What a Managed User Spent); the credits you spend with your own key are not.
  • Searching managed users by external_id in GET /managed-users. To file or list by your own id, send managedUserExternalId.
  • A picker of preset widgets inside Widgetic’s editors. Your page draws the picker and your server makes the copy (see Preset Widgets).
  • Changing entitlements yourself.

Error Handling

Common errors when working with managed users. Branch on error.code in the answer (see Errors):

Next Steps

Editor Sessions

Let a customer use Widgetic’s editors in your page

Credits & Billing

How you pay and how credits work

API Reference

Find entitlement endpoints and access levels