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:
nameis the name of the workspace.descriptionis 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:
nameis a label for the wallet.credential_type_nameis the credential type. For Miro, useDatasource.config_typeidentifies the service the wallet holds credentials for. For Miro, usemiro.
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:
nameis the name of the collection.onna_parent_idis the ID of the workspace that this collection will belong to.typeis the type of collection being created. For Miro, the type ismiro.config_typeis the configuration type. For Miro, this is alsomiro.wallet_credentialsis the ID of the wallet you created for the Miro service.
A successful response (201) will return:
{
"onna_id": "<COLLECTION_ID>",
"type": "miro"
}
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.
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_codeis 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:
limitis the number of users to return per page. For Miro the default and maximum is100; a value greater than100returns422 Limit too large.offsetis the pagination cursor. To fetch the next page, pass the value from the previous response'soffsetfield. 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:
idis the unique identifier of the user. Use this value in theselectedorexcludedarrays when configuring sync filters.valueis the user's display label (typically their name and email).offsetis the cursor for the next page of results, ornullwhen there are no more pages. To page through all users, pass this value as theoffsetquery parameter on the next request and repeat until it isnull.
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 sendteamswithall_selectedset totrueand emptyselected/excludedarrays.
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": []
}
}
}'
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:
| Field | Type | Description |
|---|---|---|
sync_status | String | Sync lifecycle state. Set to "pending" to queue a sync after filters are saved. |
sync_filters | Object | Miro sync filter configuration. Contains users and teams keys (see below). |
type_sync | String | Sync type. Supported values: "one", "arch", "auto". |
The sync_filters object contains a users key and a teams key, each with the same structure:
| Field | Type | Description |
|---|---|---|
all_selected | Boolean | If true, all entries are synchronized. When false, only the entries listed in selected are included. |
selected | Array | Entries to include when all_selected is false. For users, each entry is { "id": "<user_id>", "value": "<user_value>" } from the /users endpoint. |
excluded | Array | Entries 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.
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.