Skip to main content

Miro Collection

Miro Collection Integration with Onna

Overview

This guide explains how to set up and interact with a Miro collection through the Onna Platform API. You'll learn how to create a workspace and collection, authorize access to Miro via OAuth2, list the users available in the Miro organization, configure sync filters to control exactly which users are synchronized, start the sync, and clean up your environment afterward.

Create a workspace

A workspace is the main container for your project in Onna. Create one with a POST request.

curl --location --request POST 'https://api.onna.com/v1/workspaces' \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"name": "My New Workspace",
"description": "This is a workspace for organizing Miro data in Onna."
}'

Where:

  • name is the name of the workspace.
  • description is a brief description of the workspace's purpose.

A successful response (201) will return:

{
"onna_id": "<WORKSPACE_ID>"
}

Create a Miro Wallet

Miro credentials are stored in a wallet that the collection references. Create an empty wallet first; the OAuth pairing step later populates it with the access token.

curl --location --request POST 'https://api.onna.com/v1/wallet' \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"name": "Miro",
"credential_type_name": "Datasource",
"config_type": "miro"
}'

Where:

  • name is a label for the wallet.
  • credential_type_name is the credential type. For Miro, use Datasource.
  • config_type identifies the service the wallet holds credentials for. For Miro, use miro.

A successful response (201) will return:

{
"onna_id": "<WALLET_ID>"
}

Create a Miro Collection

Next, create a Miro collection within the workspace you created. The collection is the container for the users and content you will sync from Miro.

curl --location --request POST 'https://api.onna.com/v1/collections' \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"name": "My Miro Collection",
"onna_parent_id": "<WORKSPACE_ID>",
"type": "miro",
"config_type": "miro",
"wallet_credentials": "<WALLET_ID>"
}'

Where:

  • name is the name of the collection.
  • onna_parent_id is the ID of the workspace that this collection will belong to.
  • type is the type of collection being created. For Miro, the type is miro.
  • config_type is the configuration type. For Miro, this is also miro.
  • wallet_credentials is the ID of the wallet you created for the Miro service.

A successful response (201) will return:

{
"onna_id": "<COLLECTION_ID>",
"type": "miro"
}
Actionable Tips: While creating collections, consider adding metadata that might be required later for reporting or analysis.

You might also want to implement a naming convention (like Collection-{WorkspaceName}-Miro) for better organization.

Initiate OAuth2 Flow to Get an Authorization Code

To authorize access to Miro, initiate the OAuth2 flow. It will return an authorization URL. Open this URL in your browser to log in and grant the application access to Miro.

curl --location --request GET 'https://api.onna.com/v1/collections/authorization_url/miro?redirect_to=http%3A%2F%2Flocalhost%3A9000%2Fcallback' \
--header 'Authorization: Bearer <token>'

Once you've authorized, you'll be redirected to the provided redirect_to URL with an authorization code.

Use a temporary redirect URI during development (like http://localhost:9000/callback) for easier testing. Be sure to change this to a production-ready URL before going live.

Pair the Authorization Code with the Collection (Token Exchange)

After successful authorization, exchange the authorization code for an access token bound to the collection.

curl --location --request POST 'https://api.onna.com/v1/collections/<COLLECTION_ID>/pair_credentials?auth_code=<AUTH_CODE>' \
--header 'Authorization: Bearer <token>'

Where:

  • auth_code is the authorization code you received during the authorization process.

A successful response returns 204 No Content.

Retrieve the List of Users

To retrieve the users available in the authorized Miro organization, send a GET request to the collection's /users endpoint.

curl --location --request GET 'https://api.onna.com/v1/collections/<COLLECTION_ID>/users?limit=100' \
--header 'Authorization: Bearer <token>'

The endpoint accepts two optional query parameters:

  • limit is the number of users to return per page. For Miro the default and maximum is 100; a value greater than 100 returns 422 Limit too large.
  • offset is the pagination cursor. To fetch the next page, pass the value from the previous response's offset field. Omit it for the first page.

Example user response:

{
"users": [
{
"id": "3458764515862994209",
"value": "Lisa Simpson <lisa@onnaqa.com>"
},
{
"id": "3458764515862994315",
"value": "Bart Simpson <bart@onnaqa.com>"
}
],
"offset": null
}

Where:

  • id is the unique identifier of the user. Use this value in the selected or excluded arrays when configuring sync filters.
  • value is the user's display label (typically their name and email).
  • offset is the cursor for the next page of results, or null when there are no more pages. To page through all users, pass this value as the offset query parameter on the next request and repeat until it is null.

Configure Sync Filters

Sync filters control what is synchronized. For Miro, the sync_filters object has two keys:

  • users: the set of users to sync. This is the filter you configure.
  • teams: always set to all teams. Miro collections do not support team-level filtering, so send teams with all_selected set to true and empty selected/excluded arrays.

Update the collection with the selected configuration by sending a PATCH request.

Sync specific users

Set all_selected to false under users and list the users to include in selected. Each entry is the id and value returned by the /users endpoint.

curl --location --request PATCH 'https://api.onna.com/v1/collections/<COLLECTION_ID>' \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"sync_status": "pending",
"sync_filters": {
"users": {
"all_selected": false,
"selected": [
{ "id": "3458764515862994209", "value": "Lisa Simpson <lisa@onnaqa.com>" }
],
"excluded": []
},
"teams": {
"all_selected": true,
"selected": [],
"excluded": []
}
}
}'

Sync all users

Set all_selected to true under users with an empty selected array to sync every user in the Miro organization.

curl --location --request PATCH 'https://api.onna.com/v1/collections/<COLLECTION_ID>' \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"sync_status": "pending",
"sync_filters": {
"users": {
"all_selected": true,
"selected": [],
"excluded": []
},
"teams": {
"all_selected": true,
"selected": [],
"excluded": []
}
}
}'
Team-level filtering is not supported. Always send the teams filter with all_selected set to true (and empty selected/excluded arrays);

all teams in the organization are synchronized. User selection is the only filter you configure.

Filter fields

The top-level request fields are:

FieldTypeDescription
sync_statusStringSync lifecycle state. Set to "pending" to queue a sync after filters are saved.
sync_filtersObjectMiro sync filter configuration. Contains users and teams keys (see below).
type_syncStringSync type. Supported values: "one", "arch", "auto".

The sync_filters object contains a users key and a teams key, each with the same structure:

FieldTypeDescription
all_selectedBooleanIf true, all entries are synchronized. When false, only the entries listed in selected are included.
selectedArrayEntries to include when all_selected is false. For users, each entry is { "id": "<user_id>", "value": "<user_value>" } from the /users endpoint.
excludedArrayEntries to exclude when all_selected is true.

For teams, always send { "all_selected": true, "selected": [], "excluded": [] }; team-level filtering is not supported.

A successful PATCH returns 204 No Content, indicating the filter configuration was saved.

Update Existing Filters

To change an existing filter configuration (for example, to add or remove users), issue another PATCH to the same collection endpoint with the full updated sync_filters object. The new value replaces the previous one.

Always send the complete sync_filters object on update. Fields that are omitted are treated as removed, not merged with the previous value.

Start the Sync

Once the filters are saved, initiate the sync process.

curl --location --request POST 'https://api.onna.com/v1/collections/<COLLECTION_ID>/start' \
--header 'Authorization: Bearer <token>'

A successful response (HTTP status code 200) indicates that the sync process has begun. Only the users allowed by the configured filters are pulled into the collection.

Simulate Token Expiry and Refresh the Token

If the access token expires, you can refresh it by using the refresh token.

curl --location --request POST 'https://api.onna.com/v1/oauth/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=<client_id>' \
--data-urlencode 'client_secret=<client_secret>' \
--data-urlencode 'grant_type=refresh_token' \
--data-urlencode 'refresh_token=<refresh_token>'

This will return a new access_token and refresh_token.

{
"access_token": "<new_access_token>",
"token_type": "bearer",
"expires_in": 86399
}

Clean Up

Once you are done, you can clean up by deleting both the collection and the workspace.

curl --location --request DELETE 'https://api.onna.com/v1/collections/<COLLECTION_ID>' \
--header 'Authorization: Bearer <token>'
curl --location --request DELETE 'https://api.onna.com/v1/workspaces/<WORKSPACE_ID>' \
--header 'Authorization: Bearer <token>'

Note: Deleting a collection or workspace is permanent and cannot be undone.