Skip to main content
Embedded apps running inside Aptly can trigger UI interactions in the parent window — opening a card, starting a phone call, launching the email composer, creating an event, and more — by posting a browser message. Aptly executes the action if your app has been granted that permission. This works alongside delegate token authentication. You can use one, the other, or both.
If your app includes the Aptly SDK, use the named wrapper methods. They return a Promise<{ success: boolean, error?: string }>, handle the response listener for you, and time out after 3 seconds.
await aptly.openCardPane({ cardId: 'abc123' });
await aptly.openCardView({ cardId: 'abc123' });
await aptly.startDialer({ number: '+15551234567', name: 'Jane Smith' });
await aptly.openEmailComposer({ subject: 'Hello', content: '<p>Hi</p>', composeMode: 'email' });
await aptly.createEvent({ date: '2026-06-15T10:00:00.000Z', comments: 'Walkthrough' });
await aptly.createCard({ boardId: 'board-uuid', fields: { name: 'New Lead' } });
await aptly.createTask({ title: 'Follow up', dueAt: '2026-06-15T09:00:00.000Z', priority: 'high' });
await aptly.createContact({ firstname: 'Jane', lastname: 'Smith', email: '[email protected]' });
await aptly.navigateToContact({ contactId: 'person123' });

// Generic escape hatch — useful when the action ID is dynamic
await aptly.action('start-dialer', { number: '+15551234567' });

// Check which actions are available at runtime before calling
console.log(aptly.actions); // e.g. ['start-dialer', 'create-card']

Raw postMessage

If you are not using the SDK, post a message directly to the parent window. Aptly validates the permission and sends a response.
const APTLY_ORIGIN = 'https://app.getaptly.com'; // use https://preview.getaptly.com for preview

window.parent.postMessage(
  {
    type: 'aptly-action',
    action: 'start-dialer',
    payload: { number: '+15551234567', name: 'Jane Smith' }
  },
  APTLY_ORIGIN
);
Listen for the response:
const APTLY_ORIGINS = ['https://app.getaptly.com', 'https://preview.getaptly.com'];

window.addEventListener('message', event => {
  if (!APTLY_ORIGINS.includes(event.origin) || event.source !== window.parent) return;
  if (event.data?.type === 'aptly-action-result') {
    const { action, success, error } = event.data;
    if (!success) console.warn(`Action ${action} failed: ${error}`);
  }
});
Aptly responds with { type: 'aptly-action-result', action, success: true } or { ..., success: false, error: 'Not permitted' }.

Enabling actions for your app

Actions must be explicitly granted — nothing runs by default. An admin configures this in the settings for the specific embed. Marketplace app: In Global Admin → App Marketplace, open your app’s edit modal → Permissions tab → Embed Actions. When a user installs the app on a board, these permissions are copied to that board tab and can be adjusted in board settings. Custom board tab: In Board Settings → your tab → edit → Allowed Actions. Dashboard widget: In Dashboard → add or edit app → Embed Actions.

Available actions

open-card-pane

Navigates to a specific card in the board’s side panel.
await aptly.openCardPane({ cardId: 'abc123' });
FieldTypeRequiredDescription
cardIdstringYesThe _id of the card to open.

open-card-view

Opens a card in a fullscreen detail view (floating modal).
await aptly.openCardView({ cardId: 'abc123' });
FieldTypeRequiredDescription
cardIdstringYesThe _id of the card to open.

start-dialer

Opens the Aptly phone dialer with a number pre-filled.
await aptly.startDialer({ number: '+15551234567', name: 'Jane Smith' });
FieldTypeRequiredDescription
numberstringYesPhone number in E.164 format (+15551234567).
namestringNoContact name to display in the dialer.

open-email-composer

Opens a new email compose window, optionally pre-filled.
await aptly.openEmailComposer({
  subject: 'Follow-up on your application',
  content: '<p>Hi there,</p><p>Just following up...</p>',
  composeMode: 'email'
});
FieldTypeRequiredDescription
subjectstringNoPre-filled subject line.
contentstringNoPre-filled body content (HTML supported).
composeMode'email' | 'sms'NoDefaults to 'email'.

create-event

Opens the calendar event editor, optionally pre-filled.
await aptly.createEvent({
  date: '2026-06-15T10:00:00.000Z',
  comments: 'Property walkthrough',
  recipients: [{ email: '[email protected]', name: 'Alex Tenant' }]
});
FieldTypeRequiredDescription
dateISO 8601 stringNoPre-filled event start date/time.
commentsstringNoPre-filled event description.
recipientsarrayNoPre-filled attendees. Each object should include email and optionally name.

create-card

Opens the new card form on a specific board, optionally pre-filled.
await aptly.createCard({
  boardId: 'board-uuid-here',
  fields: {
    name: 'New Applicant',
    email: '[email protected]'
  }
});
FieldTypeRequiredDescription
boardIdstringYesUUID of the board to create the card on.
fieldsobjectNoKey-value pairs of field values to pre-fill. Keys are field UUIDs or well-known field names.

create-task

Opens the task creation form, optionally pre-filled. Common use case: a “remind me later” button that pre-fills a future due date.
await aptly.createTask({
  title: 'Follow up with tenant',
  dueAt: '2026-06-15T09:00:00.000Z',
  priority: 'high',
  note: 'Check in about lease renewal'
});
FieldTypeRequiredDescription
titlestringNoPre-filled task title.
dueAtISO 8601 stringNoPre-filled due date/time.
activityLogType'todo' | 'email' | 'sms' | 'voice'NoTask type. Defaults to 'todo'.
priority'asap' | 'high' | 'medium' | 'low'NoPre-filled priority.
notestringNoPre-filled task description.
assigneeIdstringNoUser ID to pre-assign the task to.
aptletInstanceIdstringNoCard _id to link the task to.
aptletUuidstringNoBoard UUID for context.

create-contact

Opens the contact creation modal, optionally pre-filled.
await aptly.createContact({
  firstname: 'Jane',
  lastname: 'Smith',
  phone: '+14155551234',
  email: '[email protected]'
});
FieldTypeRequiredDescription
firstnamestringNoPre-filled first name.
lastnamestringNoPre-filled last name.
phonestringNoPre-filled phone number.
emailstringNoPre-filled email address.
companystringNoPre-filled company name.
titlestringNoPre-filled job title.

Navigates to a contact’s record page.
await aptly.navigateToContact({ contactId: 'person123' });
FieldTypeRequiredDescription
contactIdstringYesThe _id of the person record to navigate to.

Troubleshooting

Action fires but nothing happens. Check that the action is listed under Allowed Actions for the specific embed where your app is running. Permission is configured per embed, not globally. Response says success: false, error: 'Not permitted'. The action is not in the embed’s allowed list. An admin needs to enable it in the app or board settings. No response message at all. Ensure your app is loaded inside an Aptly embed (not a standalone tab) and that the message is sent via window.parent. The SDK wrappers handle this correctly. open-email-composer opens but the To field is empty. Pre-filling recipients is not yet supported for this action — the user can type recipients manually after the composer opens.