Client Messaging
Application extensions and the Onshape JavaScript web client need to communicate directly, calling across the iframe containing the application extension using post message.

Client message structure
The basic client message structure is:
clientMessage = {
documentId: documentId,
workspaceId: workspaceId,
elementId: elementId,
messageName: string
};
Where messageName corresponds to one of the supported client messages for the extension type. To view the supported client messages for each extension type, see:
Security considerations
To ensure security, an application extension must:
- Parse for document, workspace, and element IDs: Parse for the
documentId,workspaceId, andelementIdthat were passed as query parameters within the application extension’s iframesrcURL. You must post these back in eachPOSTmessage. - Parse for the server: Parse for the
serverthat was passed as a query parameter within the application extension’s iframesrcURL. You must use this to validate messages received.- If the application extension uses a JavaScript library or framework (e.g., BackboneJS or AngularJS), it can parse the query parameters and maintain state in other ways.
- Not redirect to another base URL: The browser tells the Onshape client the origin base URL from which a
POSTmessage is received. The Onshape client ignores messages posted from an origin URL that doesn’t match the original iframesrcURL. It is extremely important to the security of your application that you verify that the origin of all messages you receive is the same as the original server query parameter in the iframesrc(i.e.,if (server === e.origin)). In production operation especially, the message IS NOT SAFE if the message origin does not match the iframesrcserver query parameter. Application extensions should not redirect to another base URL after the iframe has been opened, or the messages will be ignored. - Post a message on startup: Onshape will not post messages until a newly started application extension has first posted a valid message to Onshape. This constraint is in effect anytime an application extension is (re)started and exists to avoid posting messages to application extensions that are not ready to handle them, are not fully loaded, etc. After your application extension is fully loaded and ready to receive messages, post a message to Onshape. A
keepAlivemessage is a great first message to send to Onshape. Once Onshape receives a valid message, Onshape will start posting messages to the application extension. If the application extension later sends an invalid message Onshape will stop sending messages until a valid message is posted to Onshape.
POST messages submitted by application extensions to Onshape will be ignored if any of the following are true:
- The documentId, workspaceId, or elementId are missing or not valid.
- The message name is missing or not recognized.
- The origin of the
POSTmessage does not match the original iframesrcURL.
Code snippets
Parse query parameters
This JavaScript code parses the iframe src parameters and uses them to post a message:
/**
* Extracts Onshape document, workspace, and element IDs from a given URL.
* Supports both query parameter format and Onshape path-based URL format.
*
* @param {string} currentURL - The full URL string to parse.
* @returns {{ documentId: string, workspaceId: string, elementId: string }} An object containing the three Onshape IDs.
* @throws {Error} If the required IDs cannot be found in the URL.
*/
function getOnshapeIdsFromUrl(currentURL) {
const url = new URL(currentURL);
const params = url.searchParams;
const documentId = params.get('documentId');
const workspaceId = params.get('workspaceId');
const elementId = params.get('elementId');
if (documentId && workspaceId && elementId) {
return { documentId, workspaceId, elementId };
}
const pathMatch = url.pathname.match(/\/documents\/([^/]+)\/(?:w|v|m)\/([^/]+)\/e\/([^/]+)/);
if (pathMatch) {
return {
documentId: pathMatch[1],
workspaceId: pathMatch[2],
elementId: pathMatch[3]
};
}
throw new Error('Missing Onshape IDs in URL. Provide documentId, workspaceId, and elementId as query parameters or use an Onshape document URL.');
}
Create a message object
The message object posted to the Onshape client is of the form:
{
documentId: documentId,
workspaceId: workspaceId,
elementId: elementId,
messageName: '<message name>',
// … other properties as needed for other message types …
}
The message data object posted to the application extension is of the form:
{
messageName: '<message name>',
// … other properties as needed for other message types …
}
The message will always have a messageName property.
Listen for messages
To listen for messages from the Onshape client:
// server is one of the iframe src query parameters - see above
var handlePostMessage = function(e) {
console.log("Post message received in application extension.");
console.log("e.origin = " + e.origin);
// Verify the origin matches the server iframe src query parameter
if (server === e.origin) {
console.log("Message safe and can be handled as it is from origin '"
+ e.origin +
"', which matches server query parameter '"
+ server + "'.");
if (e.data && e.data.messageName) {
console.log("Message name = '" + e.data.messageName + "'");
} else {
console.log("Message name not found. Ignoring message.");
}
} else {
console.log("Message NOT safe and should be ignored.");
}
};
window.addEventListener('message', handlePostMessage, false);
Send and handle messages
The following is an example of how one might send an initialization message to, and handle post messages from, the Onshape client.
Note: Proper clean-up of event listeners is not included in the snippet
function handlePostMessage(event) {
// ensure that the event data is from a legit source:
if(theServerStringFromActionUrl !== event.origin) {
console.error('origin of message is not legitimate');
return;
}
// branch based on messageName attribute
switch(event.data.messageName) {
case 'SELECTION':
console.debug('SELECTION event data: %o', event.data);
break;
default:
console.debug(`${event.data.messageName} not handled`);
}
}
window.addEventListener('message', handlePostMessage);
const initMessage = {
documentId: theDocumentId, // required - parsed from action url
workspaceId: theWorkspaceId, // required - parsed from action url
elementId: theElementId, // required - parsed from action url
messageName: 'applicationInit' // required
};
window.parent.postMessage(initMessage, '*');
Notes
- Keyboard focus will not be transferred to an application until the user clicks in the application or the application programmatically takes focus. An application should programmatically take focus when it is first loaded and when it receives a
showmessage from Onshape. Shortcut keys will work immediately when the application is shown. - New message types will be added as needed. If your application extension needs a message not listed in this document, please notify us, and we’ll work with you on it.
- Mobile clients are currently not supported.