client_credentials token with the connections:read scope (see Access tokens):form, to open your default form. A form key that doesn't exist answers 404.{
"session": {
"token": "q4X…",
"url": "https://embed.makini.io/embed/q4X…",
"expiresAt": "2026-09-25T11:00:00.000Z"
}
}409.session.url to your page and load it in an iframe:window.postMessage. Each message is an object with an event field and the payload below.event | When | Payload |
|---|---|---|
makini:ready | The form has loaded. | None |
makini:error | The embed can't show the form. | code, message |
makini:settings.updated | Your customer saved the form. | connectionId, form (the form key) |
makini:connection.deleted | Your customer disconnected the integration. | connectionId |
makini:error codes:code | Meaning | What to do |
|---|---|---|
SESSION_EXPIRED | The session is older than one hour. | Create a new session and reload the iframe. |
CONNECTION_DEACTIVATED | The connection is switched off. | Show your own message, or reactivate the connection. |
LOAD_ERROR | The session isn't valid, or the page couldn't load. | Create a new session and retry. |
event.source so you only handle messages from your own iframe.connections:read token. Each form's answers are kept separately:{
"connectionSettings": {
"settings": {
"sync": { "sites": ["north", "south"], "create_work_orders": true },
"defaults": { "cost_center": "CC-4100" }
},
"formEnabled": true,
"formConfigVersion": 3,
"updatedAt": "2026-09-25T09:41:12.000Z"
}
}form to read your default form.settings is keyed by group key, then field key.{ "entity", "table", "fields" }. table is a raw table you can read at /v4/raw/tables/<table>. fields lists the chosen fields in your customer's order, each as a path: the column, then the keys inside it when the column holds JSON. A * segment stands for each item of a list. For example: [["status"], ["attributes", "color"], ["client", "versionedObjects", "*", "id"]].formEnabled is what Activate and Deactivate set, kept per form. While it's off, settings is {}, so nothing downstream acts on the old answers. The answers are kept and come back when your customer switches it on again.updatedAt is null until your customer saves for the first time.client_credentials token with connections:write:session.url in the same iframe.| Field | Does |
|---|---|
endCustomer.externalId | Your ID for the customer. Connections they make carry it in their metadata under your customer ID field, so they appear on that customer. |
open | Where the session opens: home, connect (with an optional platform), connection (with connectionId) or form (with connectionId and form). |
enable | Forms, solutions and flow folders to turn on for a connection made in this session, by name. |
returnUrl | Where Makini Link sends your customer after they connect. It must be one of your registered redirect URIs; leave it out to return to the embed. |
GET /connections/{id}/features lists them with what turned each one on, and PUT /connections/{id}/features sets exactly which are on.client_credentials token; reading forms needs clients:read and changing them needs clients:write.PUT creates the form when the key is new and replaces it otherwise. Makini keeps the form's version, which rises with every save. Add "isDefault": true to make it your default form, or "key" to rename it.| Route | Does |
|---|---|
GET /embed/forms | Lists your forms, the default first. |
GET /embed/forms/{key} | Reads one form with its groups and fields. |
PUT /embed/forms/{key} | Creates or replaces a form. |
DELETE /embed/forms/{key} | Deletes a form and your customers' answers to it. Make another form the default before deleting the default one. |