Importer Embedding

Your engineering team can embed OneSchema directly into your own web application by following these steps.

Importer Embedding

Enable Embedding

In your own OneSchema portal, navigate to Developer Dashboard at /developer to enable embedding by generating an Client Secret and specifying your embed domains.

There are two tokens that will be used at various parts of the embedding process: your Client ID and your Client Secret. Both of these values can be obtained from the Importer pane of the Developer Dashboard.

The Client ID is a public value and will be used in your JavaScript code to initialize an embedded session.

The Client Secret is a secret value that you will use on your servers to create a secure token for a user going the embedded import flow.

Embed Domains

When embedding OneSchema into your own site, you will create an <iframe> element that opens For security reasons, OneSchema normally sets request headers that prevent it from being embedded in another webpage. For the embed flow, you must provide OneSchema with the specific domains where OneSchema will be embedded.

You may specify multiple domains. Wildcard domains (e.g. *, domains with port numbers (e.g., and [localhost](http://localhost) domains are all supported. You will likely need multiple domains to support both your development and production environments.

Configure a Template and an Import Webhook

Before testing the embedded flow, you must create a Template that a user will use to validate their imported data. You can do this from the Templates page (/templates). Your created Template will also have a Template Key, which you will use to tell OneSchema which Template to use during the embedded import flow. Once you have set up the embed flow you can freely change the name of the Template, but you shouldn’t change the Template Key.

Once your customer completes an import, their data will be sent from OneSchema to an endpoint of your choosing using a Webhook. You can configure your Webhook in the Webhooks tab of the Developer Dashboard. Your created Webhook will have a Webhook Key, which functions similarly to the Template Key. For more information about setting up a Webhook, see our Import Webhook documentation.

If you want to get a working proof-of-concept working as quickly as possible, we recommend using to instantly create an endpoint you can use as your Webhook url.

If you do not specify a Webhook Key, the data will be included in the data of the "complete" event (see #listen-for-updates-from-the-importer).

Generate a secure JSON Web Token (JWT) for a user

When a customer completes an import, we will send their data to your specified webhook. In order for you to know which customer the data belongs to, you must provide a token identifying the user, which we will return as part of the data in the Webhook. This token should be securely generated on your server every time a user wants to perform an import.

This token must be generated securely to prevent a malicious actor from uploading data for another user. For this we will use JSON Web Tokens (JWTs) signed using your Client Secret.

The payload for the generated JWT must contain at least two fields. The iss field should be a string set to your Client ID, and the user_id field should be set to a number or string that will allow you to find the user that performed the import in your specified Webhook endpoint, e.g., a string or numeric ID. OneSchema will treat it as an opaque value and not modify it anyway. You should sign your JWT using the HS256 algorithm and your Client Secret.


In production you should generate these tokens on your server, but the Developer Dashboard also provides a helpful JWT generator to get started with testing more quickly.

In addition to the iss and user_id fields, you may also specify the following keys (with string values) in the JWT payload:

  • user_name
  • user_email
  • customer
  • metadata

The user_name, user_email, and customer fields will be displayed on the Embed Dashboard that shows a history of imports by your customers. The metadata field can be used to pass any additional data through the import flow, such as analytics tokens, monitoring and performance trace IDs, or anything else you might find useful.

Embed OneSchema in your web app

Create an iframe to``

To embed OneSchema in your web application, create an <iframe> element with a src URL pointing to:

  src="<Client ID>&dev_mode=true"

As indicated above, you should pass your Client ID in as the value of the embed_client_id query parameter.

You can also pass in dev_mode=true to enable “Developer Mode” for the embedded flow. When in Developer Mode any error messages will be directed towards you, the developer, with additional relevant information. When Developer Mode is turned off the error messages will be more end user friendly. Make sure to turn it off before launching!

You can (and should) create the iframe before the user initiates their import flow. This will reduce the time it takes for the embedded site to load.

If your iframe is failing to load, it is likely because you have not configured your embed domains properly. (You should see an error related to this in your developer console.)

Note: If you are testing on a site like, or, keep in mind that these sites nest your content within multiple iframes, each with different domains. You must add all of these domains to your list of embed domains.

Tell to start the embedded session

You will use the postMessage API to communicate with the embedded import flow.

To initialize the embedded flow, you will send an Object through postMessage with the following five fields:

  • messageType: Set this to the string "init" to start the import flow
  • userJwt: Set this to the JWT you generated for the user going through the import flow
  • templateKey: Set this to the Template Key of the Template you want use to validate the user’s data
  • webhookKey: (Optional) Set this to the Webhook Key of the Webhook you want to send the user’s data to when they complete the import. If this isn't specified, the user's data will be included as a field in the "complete" event (see #listen-for-updates-from-the-importer).
  • options: (Optional) Set this to an object with additional parameters to configure the behavior of the importer. The following options are currently supported:
let iframeElem = document.getElementById("os")
let iframe = iframeElem.contentWindow

let messageData = {
  messageType: "init",
  templateKey: "<PLACEHOLDER>",
  webhookKey: "<PLACEHOLDER>",
  userJwt: "<PLACEHOLDER>",
iframe.postMessage(messageData, "")


You must wait for the iframe to load before calling postMessage, otherwise you will see an error like this:

Failed to execute 'postMessage' on 'DomWindow': The target origin provided ('') does not match the recipient window's origin.

You can detect when the iframe loads by adding an onload event handler.

After initializing the embedded flow, for the optimal embedded experience you should style the iframe to take over the whole screen:

#os {
  postion: fixed;
  height: 100vh;
  width: 100vw;
  border: none;

/* Initially hide the iframe until the flow is initialized */
#os.hidden {
  display: none;

Listen for updates from the importer

When the user is finished with their import flow, a message will be sent back to your app using the PostMessage API with the messageType field set to "complete". If the user simply dismisses the modal, the messageType will be set to "cancel". And if an error occurs, it will be set to "error". When you receive one of these messages you can decide to hide the iframe again.

On "complete", the message will also include two important fields:

The eventId field will contain a string identifier that was included in the webhook requests. You can use this to associate the user’s session with the requests sent to your webhook. (You could also use the user JWT, which is also sent with the webhook requests, to do this.)

The responses field returns the bodies of the responses sent by your webhook endpoint. It is entirely fine to return nothing at all — you can return whatever data you’d like here. It will be array of objects with a body field containing the response, and a sequenceNumber field that indicates which request returned that response. Once this data is sent to your app you can use it however you want to guide the rest of the user’s import process.

In addition, if a Webhook Key was not specified when initializing the embedded session, a data field will be included which contains the user's data. The structure of this field is documented here.

window.addEventListener("message", (event) => {
  switch ( {
    case "complete": {
    case "cancel": {
    case "error": {
      console.log("There was an error during the embed flow",

Deleting embed user data

Data uploaded by users will automatically be deleted 7 days after upload. If you would like to manually delete the user data earlier than that you can use the External API to do so. Send a DELETE request to and pass in the Embed User JWT as a query parameter to delete all that user's associated data.

curl -X DELETE "$USER_JWT" -u ":$API_KEY"