--- url: /developers/docs/api/rate-limits.md description: Discover how the Rate Limits of the Flat Platform's API. --- # API Rate Limits The [Flat's REST API](index.html) includes a rate-limiting system that allows us to protect our quality of service. You can contact us if you need [extra quota](mailto:developers@flat.io). Authenticated requests are limited to 7,200 requests per hour. Note that some accounts may have different quotas depending on their configuration. Unauthenticated requests, which are tied to the originating IP address rather than a specific user or application, are limited to 1,800 requests per hour. To maintain the quality and stability of our service, additional rate limits may apply to certain API endpoints or actions. Some features also have their own concurrency limits, which are separate from these request-per-hour quotas. Optical Music Recognition, for example, processes up to 10 jobs in parallel per account. See the [OMR limits FAQ](/api/omr/faq/limits#what-are-the-limits). You can check the returned HTTP headers of any API request to see your current rate limit status: ```bash curl -i https://api.flat.io/v2/me HTTP/1.1 200 OK Date: Sat, 25 Mar 2017 17:06:20 GMT X-RateLimit-Limit: 7200 X-RateLimit-Remaining: 7199 X-RateLimit-Reset: 1490465178 ``` The headers tell you everything you need to know about your current rate limit status: Header name | Description \------------|------------ `X-RateLimit-Limit` | The maximum number of requests that the consumer is permitted to make per hour. `X-RateLimit-Remaining` | The number of requests remaining in the current rate limit window. This value can be negative if you try to go over the allowed quota. `X-RateLimit-Reset` | The time at which the current rate limit window resets in [UTC epoch seconds](http://en.wikipedia.org/wiki/Unix_time). If you need the time in a different format, any modern programming language can get the job done. For example, if you open up the console on your web browser, you can easily get the reset time as a JavaScript Date object. ```javascript new Date(1490465178 * 1000).toString() 'Sat Mar 25 2017 19:06:18 GMT+0100 (CET)' ``` Once you go over the rate limit you will receive an error response: ```bash curl -i https://api.flat.io/v2/me HTTP/1.1 403 Forbidden X-RateLimit-Limit: 7200 X-RateLimit-Remaining: 0 X-RateLimit-Reset: 1490465829 { "message": "API rate limit exceeded for xx.xxx.xxx.xx", "code": "API_RATE_LIMIT_EXCEEDED" } ``` --- --- url: /developers/docs/embed/api.md description: Complete reference for the Flat Embed JavaScript SDK --- # API Reference The Flat Embed SDK provides 66 methods to control and interact with embedded sheet music. ## Quick Navigation Press `⌘ + K` (Mac) or `Ctrl + K` (Windows/Linux) to search for specific methods. ## Browse by Category ### [Core Methods](./core.md) Essential methods for embed initialization and configuration (3 methods) | Method | Description | |--------|-------------| | [`ready()`](./core.md#ready) | Wait for the embed to be ready | | [`getEmbedConfig()`](./core.md#getembedconfig) | Get the embed configuration | | [`setEditorConfig()`](./core.md#seteditorconfig) | Set the editor configuration | ### [Event System](./events.md) Subscribe to and handle embed events (2 methods) | Method | Description | |--------|-------------| | [`on()`](./events.md#on) | Subscribe to a specific event | | [`off()`](./events.md#off) | Unsubscribe to a specific event | ### [Score Management](./score-management.md) Methods for loading and exporting scores in various formats (14 methods) | Method | Description | |--------|-------------| | [`loadFlatScore()`](./score-management.md#loadflatscore) | Load a score hosted on Flat | | [`loadMusicXML()`](./score-management.md#loadmusicxml) | Load a MusicXML score | | [`loadMIDI()`](./score-management.md#loadmidi) | Load a MIDI score | | [`loadJSON()`](./score-management.md#loadjson) | Load a Flat JSON score | | [`loadABC()`](./score-management.md#loadabc) | Load an ABC notation score | | [`getJSON()`](./score-management.md#getjson) | Get the score in Flat JSON format | | [`getMusicXML()`](./score-management.md#getmusicxml) | Convert the displayed score to MusicXML | | [`getPNG()`](./score-management.md#getpng) | Convert the displayed score to PNG image | | [`getMIDI()`](./score-management.md#getmidi) | Convert the displayed score to MIDI | | [`getMP3()`](./score-management.md#getmp3) | Convert the displayed score to MP3 audio | | [`getWAV()`](./score-management.md#getwav) | Convert the displayed score to WAV audio | | [`getPDF()`](./score-management.md#getpdf) | Convert the displayed score to PDF | | [`getSVG()`](./score-management.md#getsvg) | Convert the displayed score to SVG | | [`getFlatScoreMetadata()`](./score-management.md#getflatscoremetadata) | Get the metadata of the score (for scores hosted on Flat) | ### [Display & View](./display.md) Control the visual presentation of the score (6 methods) | Method | Description | |--------|-------------| | [`fullscreen()`](./display.md#fullscreen) | Toggle fullscreen mode | | [`print()`](./display.md#print) | Print the score | | [`getZoom()`](./display.md#getzoom) | Get the current zoom ratio | | [`setZoom()`](./display.md#setzoom) | Set the zoom ratio | | [`getAutoZoom()`](./display.md#getautozoom) | Get the auto-zoom status | | [`setAutoZoom()`](./display.md#setautozoom) | Enable or disable auto-zoom | ### [Playback Control](./playback.md) Control playback, volume, speed, and metronome settings (10 methods) | Method | Description | |--------|-------------| | [`play()`](./playback.md#play) | Start playback | | [`pause()`](./playback.md#pause) | Pause playback | | [`stop()`](./playback.md#stop) | Stop playback | | [`mute()`](./playback.md#mute) | Mute playback | | [`getMasterVolume()`](./playback.md#getmastervolume) | Get the current master volume | | [`setMasterVolume()`](./playback.md#setmastervolume) | Set the master volume | | [`getMetronomeMode()`](./playback.md#getmetronomemode) | Get the metronome mode | | [`setMetronomeMode()`](./playback.md#setmetronomemode) | Set the metronome mode | | [`getPlaybackSpeed()`](./playback.md#getplaybackspeed) | Get the playback speed | | [`setPlaybackSpeed()`](./playback.md#setplaybackspeed) | Set the playback speed | ### [Parts & Instruments](./parts.md) Manage individual parts, instruments, and their audio settings (12 methods) | Method | Description | |--------|-------------| | [`getPartVolume()`](./parts.md#getpartvolume) | Get the volume of a specific part | | [`setPartVolume()`](./parts.md#setpartvolume) | Set the volume of a specific part | | [`mutePart()`](./parts.md#mutepart) | Mute a specific part | | [`unmutePart()`](./parts.md#unmutepart) | Unmute a specific part | | [`setPartSoloMode()`](./parts.md#setpartsolomode) | Enable solo mode for a part | | [`unsetPartSoloMode()`](./parts.md#unsetpartsolomode) | Disable solo mode for a part | | [`getPartSoloMode()`](./parts.md#getpartsolomode) | Get the solo mode status of a part | | [`getPartReverb()`](./parts.md#getpartreverb) | Get the reverb level of a part | | [`setPartReverb()`](./parts.md#setpartreverb) | Set the reverb level of a part | | [`getParts()`](./parts.md#getparts) | Get information about all parts | | [`getDisplayedParts()`](./parts.md#getdisplayedparts) | Get the currently displayed parts | | [`setDisplayedParts()`](./parts.md#setdisplayedparts) | Set which parts to display | ### [Audio/Video Tracks](./tracks.md) Synchronize external audio or video with the score (3 methods) | Method | Description | |--------|-------------| | [`setTrack()`](./tracks.md#settrack) | Configure an audio or video track | | [`useTrack()`](./tracks.md#usetrack) | Enable a previously configured track | | [`seekTrackTo()`](./tracks.md#seektrackto) | Seek to a position in the audio track | ### [Navigation & Cursor](./navigation.md) Navigate through the score and control cursor position (6 methods) | Method | Description | |--------|-------------| | [`focusScore()`](./navigation.md#focusscore) | Set focus to the score | | [`getCursorPosition()`](./navigation.md#getcursorposition) | Get the cursor position | | [`setCursorPosition()`](./navigation.md#setcursorposition) | Set the cursor position | | [`goLeft()`](./navigation.md#goleft) | Move cursor left | | [`goRight()`](./navigation.md#goright) | Move cursor right | | [`scrollToCursor()`](./navigation.md#scrolltocursor) | Scroll to cursor position | ### [Score Data & Structure](./data.md) Access and query score structure, measures, notes, and metadata (10 methods) | Method | Description | |--------|-------------| | [`getNbMeasures()`](./data.md#getnbmeasures) | Get the number of measures in the score | | [`getMeasuresUuids()`](./data.md#getmeasuresuuids) | Get the measure UUIDs of the score | | [`getMeasureDetails()`](./data.md#getmeasuredetails) | Get detailed measure information | | [`getNbParts()`](./data.md#getnbparts) | Get the number of parts in the score | | [`getPartsUuids()`](./data.md#getpartsuuids) | Get the part UUIDs of the score | | [`getMeasureVoicesUuids()`](./data.md#getmeasurevoicesuuids) | Get voice UUIDs for a specific measure | | [`getMeasureNbNotes()`](./data.md#getmeasurenbnotes) | Get the number of notes in a voice | | [`getNoteData()`](./data.md#getnotedata) | Get information about a specific note | | [`playbackPositionToNoteIdx()`](./data.md#playbackpositiontonoteidx) | Convert playback position to note index | | [`getNoteDetails()`](./data.md#getnotedetails) | Get note details at cursor position | ## All Methods | Method | Description | |--------|-------------| | [`focusScore()`](./navigation.md#focusscore) | Set focus to the score | | [`fullscreen()`](./display.md#fullscreen) | Toggle fullscreen mode | | [`getAutoZoom()`](./display.md#getautozoom) | Get the auto-zoom status | | [`getCursorPosition()`](./navigation.md#getcursorposition) | Get the cursor position | | [`getDisplayedParts()`](./parts.md#getdisplayedparts) | Get the currently displayed parts | | [`getEmbedConfig()`](./core.md#getembedconfig) | Get the embed configuration | | [`getFlatScoreMetadata()`](./score-management.md#getflatscoremetadata) | Get the metadata of the score (for scores hosted on Flat) | | [`getJSON()`](./score-management.md#getjson) | Get the score in Flat JSON format | | [`getMasterVolume()`](./playback.md#getmastervolume) | Get the current master volume | | [`getMeasureDetails()`](./data.md#getmeasuredetails) | Get detailed measure information | | [`getMeasureNbNotes()`](./data.md#getmeasurenbnotes) | Get the number of notes in a voice | | [`getMeasuresUuids()`](./data.md#getmeasuresuuids) | Get the measure UUIDs of the score | | [`getMeasureVoicesUuids()`](./data.md#getmeasurevoicesuuids) | Get voice UUIDs for a specific measure | | [`getMetronomeMode()`](./playback.md#getmetronomemode) | Get the metronome mode | | [`getMIDI()`](./score-management.md#getmidi) | Convert the displayed score to MIDI | | [`getMP3()`](./score-management.md#getmp3) | Convert the displayed score to MP3 audio | | [`getMusicXML()`](./score-management.md#getmusicxml) | Convert the displayed score to MusicXML | | [`getNbMeasures()`](./data.md#getnbmeasures) | Get the number of measures in the score | | [`getNbParts()`](./data.md#getnbparts) | Get the number of parts in the score | | [`getNoteData()`](./data.md#getnotedata) | Get information about a specific note | | [`getNoteDetails()`](./data.md#getnotedetails) | Get note details at cursor position | | [`getPartReverb()`](./parts.md#getpartreverb) | Get the reverb level of a part | | [`getParts()`](./parts.md#getparts) | Get information about all parts | | [`getPartSoloMode()`](./parts.md#getpartsolomode) | Get the solo mode status of a part | | [`getPartsUuids()`](./data.md#getpartsuuids) | Get the part UUIDs of the score | | [`getPartVolume()`](./parts.md#getpartvolume) | Get the volume of a specific part | | [`getPDF()`](./score-management.md#getpdf) | Convert the displayed score to PDF | | [`getPlaybackSpeed()`](./playback.md#getplaybackspeed) | Get the playback speed | | [`getPNG()`](./score-management.md#getpng) | Convert the displayed score to PNG image | | [`getSVG()`](./score-management.md#getsvg) | Convert the displayed score to SVG | | [`getWAV()`](./score-management.md#getwav) | Convert the displayed score to WAV audio | | [`getZoom()`](./display.md#getzoom) | Get the current zoom ratio | | [`goLeft()`](./navigation.md#goleft) | Move cursor left | | [`goRight()`](./navigation.md#goright) | Move cursor right | | [`loadABC()`](./score-management.md#loadabc) | Load an ABC notation score | | [`loadFlatScore()`](./score-management.md#loadflatscore) | Load a score hosted on Flat | | [`loadJSON()`](./score-management.md#loadjson) | Load a Flat JSON score | | [`loadMIDI()`](./score-management.md#loadmidi) | Load a MIDI score | | [`loadMusicXML()`](./score-management.md#loadmusicxml) | Load a MusicXML score | | [`mute()`](./playback.md#mute) | Mute playback | | [`mutePart()`](./parts.md#mutepart) | Mute a specific part | | [`off()`](./events.md#off) | Unsubscribe to a specific event | | [`on()`](./events.md#on) | Subscribe to a specific event | | [`pause()`](./playback.md#pause) | Pause playback | | [`play()`](./playback.md#play) | Start playback | | [`playbackPositionToNoteIdx()`](./data.md#playbackpositiontonoteidx) | Convert playback position to note index | | [`print()`](./display.md#print) | Print the score | | [`ready()`](./core.md#ready) | Wait for the embed to be ready | | [`scrollToCursor()`](./navigation.md#scrolltocursor) | Scroll to cursor position | | [`seekTrackTo()`](./tracks.md#seektrackto) | Seek to a position in the audio track | | [`setAutoZoom()`](./display.md#setautozoom) | Enable or disable auto-zoom | | [`setCursorPosition()`](./navigation.md#setcursorposition) | Set the cursor position | | [`setDisplayedParts()`](./parts.md#setdisplayedparts) | Set which parts to display | | [`setEditorConfig()`](./core.md#seteditorconfig) | Set the editor configuration | | [`setMasterVolume()`](./playback.md#setmastervolume) | Set the master volume | | [`setMetronomeMode()`](./playback.md#setmetronomemode) | Set the metronome mode | | [`setPartReverb()`](./parts.md#setpartreverb) | Set the reverb level of a part | | [`setPartSoloMode()`](./parts.md#setpartsolomode) | Enable solo mode for a part | | [`setPartVolume()`](./parts.md#setpartvolume) | Set the volume of a specific part | | [`setPlaybackSpeed()`](./playback.md#setplaybackspeed) | Set the playback speed | | [`setTrack()`](./tracks.md#settrack) | Configure an audio or video track | | [`setZoom()`](./display.md#setzoom) | Set the zoom ratio | | [`stop()`](./playback.md#stop) | Stop playback | | [`unmutePart()`](./parts.md#unmutepart) | Unmute a specific part | | [`unsetPartSoloMode()`](./parts.md#unsetpartsolomode) | Disable solo mode for a part | | [`useTrack()`](./tracks.md#usetrack) | Enable a previously configured track | --- --- url: /developers/docs/embed/api/tracks.md description: Synchronize external audio or video with the score --- # Audio/Video Tracks Synchronize external audio or video with the score ## Methods ### setTrack() {#settrack} Configure an audio or video track Sets up a new audio or video track to synchronize with the score playback. This allows you to play backing tracks, reference recordings, or video alongside the score. ```typescript setTrack(parameters: ScoreTrackConfiguration): Promise ``` **Parameters:** * `parameters` - `ScoreTrackConfiguration` **ScoreTrackConfiguration** Configuration for audio/video track synchronization with score Properties: * `id`: `string` - Unique identifier for this track configuration * `type`: `ScoreTrackType` - The type of media track * `url` *(optional)*: `string` - URL of the media file (required for 'soundcloud' and 'audio' types) * `mediaId` *(optional)*: `string` - Video/media identifier (required for 'youtube' and 'vimeo' types) * `totalTime` *(optional)*: `number` - Total duration in seconds (required for 'external' type) * `synchronizationPoints`: `ScoreTrackSynchronizationPoint[]` - List of synchronization points between score and media **Returns:** `Promise` **Throws:** * `Error` - If the track configuration is invalid **Example:** ```typescript const embed = new Embed('container', config); await embed.setTrack({ id: 'backing-track', type: 'audio', url: 'https://example.com/track.mp3', synchronizationPoints: [ { type: 'measure', measure: 0, time: 0 } ] }); ``` **See also:** * [`useTrack()`](#usetrack) - Enable a configured track * [`seekTrackTo()`](#seektrackto) - Seek to a position in the track *** ### useTrack() {#usetrack} Enable a previously configured track Activates a track that was previously configured with `setTrack()`. Only one track can be active at a time. ```typescript useTrack(parameters: { id: string; }): Promise ``` **Parameters:** * `parameters.id` - `string` **Returns:** `Promise` **Throws:** * `Error` - If the track ID is invalid or track cannot be enabled **Examples:** ```typescript // Enable a configured backing track await embed.useTrack({ id: 'backing-track-1' }); ``` **See also:** * [`setTrack()`](#settrack) - Configure a new track *** ### seekTrackTo() {#seektrackto} Seek to a position in the audio track Moves the playback position of the currently active audio/video track to a specific time. This is useful for synchronizing with score playback or jumping to specific sections. ```typescript seekTrackTo(parameters: { time: number; }): Promise ``` **Parameters:** * `parameters.time` - `number` **Returns:** `Promise` **Throws:** * `Error` - If no track is active or seeking fails **Examples:** ```typescript // Seek to 30 seconds await embed.seekTrackTo({ time: 30 }); ``` **See also:** * [`setTrack()`](#settrack) - Configure a track * [`useTrack()`](#usetrack) - Enable a track *** --- --- url: /developers/docs/api/omr/import.md description: >- Import a PDF of sheet music into Flat with Optical Music Recognition (OMR) through a single unified endpoint. Send the file to POST /scores, poll the task, and get an editable score. --- # Auto simple PDF import The simplest way to run OMR is the regular score import: send a PDF to [`POST /scores`](https://flat.io/developers/docs/api/reference#tag/Score/operation/createScore) and Flat imports it as an editable score. This is the **same endpoint** you use for MusicXML and MIDI, so one code path handles every format. It is the right choice when you just want a score in the Library and do not need progress updates or a review step. Unlike MusicXML or MIDI (which import synchronously), OMR takes some time, so a PDF import is handled as an **asynchronous task**: 1. You start the import with `POST /scores`. The API replies immediately with a **task**. 2. You **poll the task** until it is done. 3. Once done, you retrieve (and optionally export) the newly created score. In this page: * [Prerequisites](#prerequisites) * [Step 1. Start the import](#step-1-start-the-import) * [Step 2. Poll the task](#step-2-poll-the-task) * [Step 3. Retrieve the imported score](#step-3-retrieve-the-imported-score) * [Error handling](#error-handling) * [Usage and billing](#usage-and-billing) * [Related](#related) > Need live progress, an instrument-correction review step, MusicXML-only output, or incremental > (mobile) capture? Use the [Interactive Jobs API](/api/omr/jobs) instead. New to OMR? Start with the > [OMR overview](/api/omr/). ## Prerequisites * **Authentication.** A [Personal Access Token](/api/authentication#personal-access-tokens) works nicely to get started quickly. If you are building an OAuth2 app, request the `scores` scope (to create the score), the `omr` scope (to run OMR), and the `tasks.readonly` scope (to poll the task). * **File format.** Only **PDF** (`application/pdf`) files go through OMR. * **Encoding.** Binary PDF data must be Base64-encoded and sent in the `data` property, with `dataEncoding` set to `base64`. * **Opt in to tasks.** You must set `supportsTasks: true` in the request. Without it, a PDF import is rejected. ## Step 1. Start the import Create the score with [`POST /scores`](https://flat.io/developers/docs/api/reference#tag/Score/operation/createScore), providing the Base64-encoded PDF and `supportsTasks: true`: ::: code-group ```bash [curl] curl -X POST 'https://api.flat.io/v2/scores' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ -d '{ "title": "My imported score", "filename": "my-sheet-music.pdf", "data": "", "dataEncoding": "base64", "supportsTasks": true }' ``` ```js [JavaScript] import { readFileSync } from 'node:fs'; const res = await fetch('https://api.flat.io/v2/scores', { method: 'POST', headers: { Authorization: 'Bearer ', 'Content-Type': 'application/json', }, body: JSON.stringify({ title: 'My imported score', filename: 'my-sheet-music.pdf', data: readFileSync('my-sheet-music.pdf').toString('base64'), dataEncoding: 'base64', supportsTasks: true, }), }); // A PDF import returns 202 with a task; MusicXML/MIDI return 200 with the score. const task = await res.json(); ``` ```python [Python] import base64, requests with open("my-sheet-music.pdf", "rb") as f: data = base64.b64encode(f.read()).decode() res = requests.post( "https://api.flat.io/v2/scores", headers={"Authorization": "Bearer "}, json={ "title": "My imported score", "filename": "my-sheet-music.pdf", "data": data, "dataEncoding": "base64", "supportsTasks": True, }, ) # A PDF import returns 202 with a task; MusicXML/MIDI return 200 with the score. task = res.json() ``` ::: Because the PDF requires OMR, the API responds with **`202 Accepted`** and a task instead of the score: ```json { "id": "5e0a59c0f1e6b8000868e0c1", "type": "import-omr", "state": "created", "progress": { "percent": 0 }, "creationDate": "2026-06-16T09:24:00.000Z" } ``` Keep the task `id`. You will use it to follow the import. ::: tip Branch on the HTTP status MusicXML and MIDI imports are processed synchronously and still return **`200 OK`** with the full score. A PDF import returns **`202 Accepted`** with a task. Have your client branch on the status code: `200` means the score is ready, `202` means follow the task flow below. ::: ## Step 2. Poll the task Fetch the task with [`GET /tasks/{task}`](https://flat.io/developers/docs/api/reference#tag/Task/operation/getTask) until it completes: ::: code-group ```bash [curl] curl -H 'Authorization: Bearer ' \ https://api.flat.io/v2/tasks/5e0a59c0f1e6b8000868e0c1 ``` ```js [JavaScript] async function waitForTask(taskId, token) { while (true) { const res = await fetch(`https://api.flat.io/v2/tasks/${taskId}`, { headers: { Authorization: `Bearer ${token}` }, }); const task = await res.json(); if (['done', 'error', 'canceled'].includes(task.state)) return task; await new Promise((r) => setTimeout(r, 3000)); // poll every few seconds } } ``` ```python [Python] import time, requests def wait_for_task(task_id, token): while True: task = requests.get( f"https://api.flat.io/v2/tasks/{task_id}", headers={"Authorization": f"Bearer {token}"}, ).json() if task["state"] in ("done", "error", "canceled"): return task time.sleep(3) # poll every few seconds ``` ::: The task moves through the following states: | `state` | Meaning | |:-----------|:---------------------------------------------------------------| | `created` | The task is queued and waiting to be processed. | | `blocked` | The task is waiting on something else before it can run. | | `doing` | OMR processing is in progress (see `progress.percent`). | | `done` | The score has been imported. The `score` field is set. | | `canceled` | The task was canceled and will not complete. | | `error` | Processing failed. See `result.error`. | `created`, `blocked`, and `doing` are transient; `done`, `canceled`, and `error` are terminal. Stop polling on any of the three terminal states, not just `done` and `error`, or a canceled task will loop forever. The fields you care about while polling: | Field | Description | |:------------------|:------------------------------------------------------------------------| | `id` | Unique identifier of the task. | | `type` | `import-omr` for an OMR import. | | `state` | Current state of the task (see table above). | | `progress.percent`| Progression of the task, from `0` to `100`. | | `score` | The unique identifier of the imported score (set once `state` is `done`).| | `result.error` | A human-readable error message when `state` is `error`. | A completed task looks like: ```json { "id": "5e0a59c0f1e6b8000868e0c1", "type": "import-omr", "state": "done", "score": "5e0a5b2cf1e6b8000868e0d4", "revision": "5e0a5b2cf1e6b8000868e0d5", "progress": { "percent": 100 }, "creationDate": "2026-06-16T09:24:00.000Z", "doneDate": "2026-06-16T09:25:12.000Z" } ``` Poll every few seconds rather than in a tight loop, and respect our [rate limits](/api/rate-limits). ## Step 3. Retrieve the imported score Once the task is `done`, read the `score` field for the new score identifier, then fetch the full score details with [`GET /scores/{score}`](https://flat.io/developers/docs/api/reference#tag/Score/operation/getScore): ::: code-group ```bash [curl] curl -H 'Authorization: Bearer ' \ https://api.flat.io/v2/scores/5e0a5b2cf1e6b8000868e0d4 ``` ```js [JavaScript] const res = await fetch(`https://api.flat.io/v2/scores/${task.score}`, { headers: { Authorization: `Bearer ${token}` }, }); const score = await res.json(); ``` ```python [Python] score = requests.get( f"https://api.flat.io/v2/scores/{task['score']}", headers={"Authorization": f"Bearer {token}"}, ).json() ``` ::: From there, the score behaves like any other Flat score. You can also **export** it to other formats, for example **MusicXML**, **MP3**, or **MIDI**, using the [score export endpoints](https://flat.io/developers/docs/api/reference#tag/Score/operation/createScoreRevisionExport). Exporting follows the **same asynchronous task pattern** as the import: create the export task, poll [`GET /tasks/{task}`](https://flat.io/developers/docs/api/reference#tag/Task/operation/getTask), then download the result from the task's `result.url` once it is `done`. ## Error handling | Status | When it happens | |:-------|:-----------------------------------------------------------------------------------------------------| | `400` | Bad request, for example a missing `supportsTasks: true`, or an invalid or password-protected PDF. | | `402` | The account is over quota, the OMR feature is not included in the plan, or there are not enough credits. See [Usage and billing](#usage-and-billing).| | `403` | The OAuth2 token is missing the `omr` scope (`OMR_SCOPE_REQUIRED`), or the `scores` scope needed to create the score. | In addition, a task may finish in the `error` state. When that happens, inspect `result.error` for a description of what went wrong. See the [Errors](/api/errors) page for the general error format, and the [OMR overview](/api/omr/#errors) for the full list of recognition failure codes. ## Usage and billing OMR imports consume the **credits of the Flat account that owns the token**, charged per page: **1 credit is 1 page**, drawn from the same pool as the Flat web, desktop, and mobile apps. With a Personal Access Token that is your own account; with OAuth2, the account of the user who authorized your app. Credits come from the account's Flat or Flat for Education subscription allowance first, then from credit packs bought on [flat.io/settings/ai-credits](https://flat.io/settings/ai-credits?ref=dev-docs-omr). Out of credits means a `402`. See [Capabilities and credits](/api/omr/#capabilities-and-credits) for the full picture, including how to read `remainingCredits` before you start an import, and the [credits and billing FAQ](/api/omr/faq/credits) for refunds, packs, and volume pricing. If you need higher volumes or have specific requirements, reach out to us at . We are happy to discuss the best setup for your use case. ## Related * [OMR overview](/api/omr/) - scopes, credits, capabilities, and error codes. * [Interactive Jobs API](/api/omr/jobs) - progress, the instrument-review step, and MusicXML output. * [FAQ](/api/omr/faq/) - credits and billing, limits, recognition quality, and commercial use. * [API Reference: `createScore`](https://flat.io/developers/docs/api/reference#tag/Score/operation/createScore) and [`getTask`](https://flat.io/developers/docs/api/reference#tag/Task/operation/getTask). * [Authentication](/api/authentication). --- --- url: /developers/docs/lti/usage.md description: >- Flat is an LTI Provider. If you are using an LTI consumer, check out our information on how you can use Flat with your product. --- # Certified LTI Provider [Flat for Education is a certified LTI Provider](https://site.imsglobal.org/certifications/tutteo-ltd/flat-for-education), ensuring seamless interaction with any LTI Consumer/Platform. If your institution uses an LTI-compatible platform, you can easily integrate it with [Flat for Education](https://flat.io/edu). ## [LTI 1.3 (Advantage)](./lti-1.3) LTI 1.3 is our recommended integration method. We support the full [LTI Advantage](https://www.imsglobal.org/lti-advantage-overview) suite, including Deep Linking, Assignment & Grade Services, Names and Role Provisioning Services, and Submission Review. [Read the LTI 1.3 documentation](./lti-1.3) ## [LTI 1.1 (Legacy)](./lti-1.1) We continue to support LTI 1.0 and 1.1 for platforms that have not yet migrated to LTI 1.3. We recommend upgrading to LTI 1.3 for improved security and features. [Read the LTI 1.1 documentation](./lti-1.1) ## Contact For questions about our LTI integration or to discuss a custom integration, please contact us at . --- --- url: /developers/docs/embed/api/core.md description: Essential methods for embed initialization and configuration --- # Core Methods Essential methods for embed initialization and configuration ## Methods ### ready() {#ready} Wait for the embed to be ready Returns a promise that resolves when the embed iframe has fully loaded and communication with the Flat embed has been established. This method is automatically called by all other embed methods, so you typically don't need to call it directly. However, it can be useful when you want to know exactly when the embed is ready without performing any other action. ```typescript ready(): Promise ``` **Returns:** `Promise` **Examples:** ```typescript // Explicitly wait for embed to be ready const embed = new Embed('container', { score: '56ae21579a127715a02901a6' }); await embed.ready(); console.log('Embed is now ready!'); ``` **Note:** All embed methods automatically call ready() internally, so explicit calls are optional *** ### getEmbedConfig() {#getembedconfig} Get the embed configuration Retrieves the complete configuration object for the embed, including display settings, permissions, editor configuration, and enabled features. ```typescript getEmbedConfig(): Promise> ``` **Returns:** `Promise>` **Throws:** * `Error` - If the configuration cannot be retrieved **Examples:** ```typescript // Get current embed configuration const config = await embed.getEmbedConfig(); console.log(`Mode: ${config.mode}`); console.log(`Controls enabled: ${config.controlsPlay}`); ``` *** ### setEditorConfig() {#seteditorconfig} Set the editor configuration Updates the editor configuration for the embed. These settings control various aspects of the editor interface and behavior. The configuration is applied when the next score is loaded. ```typescript setEditorConfig(editor: Record): Promise ``` **Parameters:** * `editor` - `Record` **Returns:** `Promise` **Throws:** * `Error` - If the configuration is invalid **Example:** ```typescript const embed = new Embed('container', config); await embed.setEditorConfig('value'); ``` **Note:** This configuration persists across score loads until changed *** --- --- url: /developers/docs/embed/api/display.md description: Control the visual presentation of the score --- # Display & View Control the visual presentation of the score ## Methods ### fullscreen() {#fullscreen} Toggle fullscreen mode Switches the embed in or out of fullscreen mode. When in fullscreen, the embed expands to fill the entire screen, providing an immersive view of the score. ```typescript fullscreen(active: boolean): Promise ``` **Parameters:** * `active` - `boolean` **Returns:** `Promise` **Throws:** * `Error` - If fullscreen mode cannot be toggled (e.g., browser restrictions) **Examples:** ```typescript // Enter fullscreen mode await embed.fullscreen(true); ``` ```typescript // Exit fullscreen mode await embed.fullscreen(false); ``` **Note:** Fullscreen requests may require user interaction due to browser policies *** ### print() {#print} Print the score Opens the browser's print dialog to print the currently loaded score. The score is formatted for optimal printing with proper page breaks and sizing. ```typescript print(): Promise ``` **Returns:** `Promise` **Throws:** * `Error` - If no score is loaded or printing cannot be initiated **Examples:** ```typescript // Print the current score await embed.print(); ``` **Note:** The actual printing is controlled by the browser's print dialog *** ### getZoom() {#getzoom} Get the current zoom ratio Retrieves the current zoom level of the score display. The zoom level affects how large the notation appears on screen. ```typescript getZoom(): Promise ``` **Returns:** `Promise` **Throws:** * `Error` - If the zoom level cannot be retrieved **Example:** ```typescript const embed = new Embed('container', config); const zoom = await embed.getZoom(); console.log(zoom); ``` **See also:** * [`setZoom()`](#setzoom) - Set the zoom level * [`getAutoZoom()`](#getautozoom) - Check if auto-zoom is enabled *** ### setZoom() {#setzoom} Set the zoom ratio Sets a specific zoom level for the score display. Setting a manual zoom level automatically disables auto-zoom mode. ```typescript setZoom(zoom: number): Promise ``` **Parameters:** * `zoom` - `number` **Returns:** `Promise` **Throws:** * `Error` - If the zoom value is outside the valid range **Examples:** ```typescript // Set zoom to 150% await embed.setZoom(1.5); ``` **See also:** * [`getZoom()`](#getzoom) - Get current zoom level * [`setAutoZoom()`](#setautozoom) - Enable automatic zoom *** ### getAutoZoom() {#getautozoom} Get the auto-zoom status Checks whether auto-zoom mode is currently enabled. When auto-zoom is active, the score automatically adjusts its zoom level to fit the available space. ```typescript getAutoZoom(): Promise ``` **Returns:** `Promise` **Throws:** * `Error` - If the status cannot be retrieved **Example:** ```typescript const embed = new Embed('container', config); const autoZoom = await embed.getAutoZoom(); console.log(autoZoom); ``` **See also:** * [`setAutoZoom()`](#setautozoom) - Enable or disable auto-zoom *** ### setAutoZoom() {#setautozoom} Enable or disable auto-zoom Controls the auto-zoom feature. When enabled, the score automatically adjusts its zoom level to fit the available container width. When disabled, the zoom level remains fixed at the last set value. ```typescript setAutoZoom(state: boolean): Promise ``` **Parameters:** * `state` - `boolean` **Returns:** `Promise` **Throws:** * `Error` - If auto-zoom cannot be toggled **Examples:** ```typescript // Enable auto-zoom await embed.setAutoZoom(true); ``` **See also:** * [`getAutoZoom()`](#getautozoom) - Check current auto-zoom status * [`setZoom()`](#setzoom) - Set a specific zoom level *** --- --- url: /developers/docs/embed/changelog.md description: Changelog for Flat's JavaScript/TypeScript Embed SDK (flat-embed) --- # Embed SDK Changelog ## 2026-04-02: v2.12.1 * Fixed TypeScript declaration output path broken by TypeScript 6 upgrade ## 2026-04-02: v2.12.0 * Added method `getSVG` for SVG export ## 2026-03-19: v2.11.0 * Added method `loadABC` for ABC notation loading ## 2026-03-03: v2.10.0 * Added `editorInterface` parameter to `EmbedUrlParameters` type (`'desktop'` | `'mobile'`) ## 2026-02-16: v2.9.0 * Added methods `getMP3` and `getWAV` for audio export * Added event `exportProgress` ## 2026-02-06: v2.8.0 * Added method `getPDF` for PDF export ## 2025-12-29: v2.7.0 * Added event `embedSize` ## 2025-10-22: v2.6.0 * Added support for new locales: Danish (`da`), Finnish (`fi`), Filipino (`fil`), French Canadian (`fr-CA`), Hindi (`hi`), Indonesian (`id`), Malay (`ms`), Norwegian Bokmål (`nb`), Traditional Chinese Hong Kong (`zh-HK`), and Traditional Chinese Taiwan (`zh-TW`) ## 2025-09-23: v2.5.1 * NPM Trusted publishing ## 2025-08-04: v2.5.0 * Enhanced TypeScript types and new documentation ## 2025-04-10: v2.4.1 * Added missing `mode` to `EmbedUrlParameters` TypeScript interface ## 2025-03-10: v2.4.0 * Added method `loadMIDI` ## 2024-01-03: v2.3.0 * Added `lazy` option to add a `loading="lazy"` attribute to the created iframe ## 2023-11-24: v2.2.0 * Added embed parameter `userId` ## 2023-10-02: v2.1.0 * Added methods: * `getNbParts` * `getPartsUuids` * `getMeasureVoicesUuids` * `getMeasureNbNotes` * `getNoteData` * `playbackPositionToNoteIdx` * Added URL parameter: * `noAudio` to disable audio playback * Fixed `setMasterVolume` not calling the correct underlying method ## 2023-09-27: v2.0.1 * Fixed package `exports` compatibility with Webpack 5 ## 2023-09-27: v2.0.0 **Breaking changes**: * Removed support for jQuery in constructor. Migration: ```js var container = $('#embed-container'); var embed = new Flat.Embed(container[0], { // your options }); ``` **New features**: * Added support for TypeScript in published NPM module * Publishing separate ES & UMD builds ## 2023-04-04: v1.5.1 * Add `allow: autoplay` on created iframes. ## 2023-03-08: v1.5.0 * Add methods: * `getNbMeasures` * `getMeasuresUuids` * `goLeft` * `goRight` * `getMetronomeMode` * `setMetronomeMode` * `getPlaybackSpeed` * `setPlaybackSpeed` * `scrollToCursor` ## 2022-04-22: v1.4.1 * Fixed compatibility with Vue 3 ## 2021-04-28: v1.4.0 * Update `loadFlatScore` to support `sharingKey` * Add methods to dynamically set audio tracks: `setTrack`, `useTrack` and `seekTrackTo` ## 2020-05-06: Available with all previous SDKs since 0.4.0 * new options for `getPNG` * `layout` with `track` or `page` (default: `track`) * `dpi` ## 2020-02-24: v1.3.0 * Add methods: * `getMasterVolume` * `setMasterVolume` * `getPartVolume` * `setPartVolume` * `mutePart` * `unmutePart` * `setPartSoloMode` * `unsetPartSoloMode` * `getPartSoloMode` * `getPartReverb` * `setPartReverb` * `getMeasureDetails` * `getNoteDetails` * Add events: * `noteDetails` * `measureDetails` * `cursorContext` ## 2020-01-07: v1.2.0 * Add methods: `getParts`, `getDisplayedParts` and `setDisplayedParts` ## 2019-05-13: v1.1.0 * Support for MIDI Output ## 2019-05-05: v1.0.0 * Host on our CDN (`https://prod.flat-cdn.com/embed-js/${VERSION}/embed.min.js`) ## 2018-11-29: v0.11.0 * Add `getMIDI` update * Update `getMusicXML` to support new returned Uint8Array format (no more `.data`, response is at top level) * Update cursor: `voiceIdx` is now `voiceIdxInStaff` ## 2018-11-23: v0.10.0 * Update for the embed release * Use new CDN endpoint `flat-embed.com` by default * Remove deprecated `edit` action & event * Remove `setNoteColor` method ## 2017-11-10: v0.9.0 * Add method: `mute` ## 2017-10-19: v0.8.0 * Switch from babel-preset-es2015 to babel-preset-env * Remove rollup-plugin-hypothetical and babel-plugin-transform-runtime ## 2017-08-08: v0.7.0 * Add method: `setNoteColor` ## 2017-08-03: v0.6.0 * Add methods: `getCursorPosition` and `setCursorPosition` ## 2017-07-07: v0.5.0 * Add method: `focusScore` * New property `defaultMode` in editor config ## 2017-07-05: v0.4.0 * Add method: `getPNG` ## 2017-05-03: v0.3.0 * Add methods: `getEmbedConfig`, `setEditorConfig`, `edit` * Add events: `edit` ## 2017-04-21: v0.2.0 * Add methods: `getAutoZoom`, `setAutoZoom`, `loadMusicXML`, `getMusicXML` * Add events: `scoreLoaded`, `cursorPosition`, `rangeSelection`, `pause`, `stop`, `fullscreen`, `print` * Add integration tests ## 2017-04-21: v0.1.0 * Initial release --- --- url: /developers/docs/embed/javascript-editor.md description: Allow your website visitor and users to edit any sheet music --- # Embeddable music notation editor You can use our [JavaScript SDK](javascript) to embed our editor anywhere. Load any MusicXML files or scores hosted on Flat, edit them directly on your webpage or app, then export them to MusicXML or MIDI directly in JavaScript. The embeddable editor requires an [Embed plan](https://flat.io/embed) that includes edit mode. Applications on the free plan can display scores but not edit them: they fall back to `view` mode. ::: warning The `appId` in these examples is ours, not yours The examples on this page use a demo `appId` on a plan that includes edit mode, so they open the editor. Replacing it with the `appId` of an application without edit mode makes the same code render a read-only score: `mode: 'edit'` falls back to `view` and no error is raised. Check the plan of your application in your [developer settings](https://flat.io/developers/apps) if the editor does not appear. ::: You can also use our [code generator](https://flat.io/developers/embed/generator) to generate the JavaScript initializing our embeddable editor with the customizations options you want. Here is a simple example using the same score [from our introduction](/embed/) as an editable template you can export once edited. Here is how the example is done. [You can view and edit this complete example on Code Sandbox](https://codesandbox.io/s/github/FlatIO/embed-demo-editor-simple). ```html
``` ## Real-life example Another good example of application using this SDK with the editor is [our Google Docs add-ons](https://gsuite.google.com/marketplace/app/flat_for_docs/324260072797). They load some MusicXML templates, then export the score to MusicXML and PNG once the creation is done. --- --- url: /developers/docs/embed/api/events.md description: Subscribe to and handle embed events --- # Event System Subscribe to and handle embed events. Events are broadcasted following actions made by the end-user or you with the JavaScript API. ## Event Methods ### on() {#on} Subscribe to a specific event. When an event includes some data, this data will be available in the first parameter of the listener callback. ```typescript on(event: EmbedEventName, callback: () => void): void ``` **Parameters:** * `event` - `EmbedEventName` - The name of the event to subscribe to * `callback` - `() => void` - The callback function to execute when the event is triggered **Returns:** `void` **Example:** ```typescript const embed = new Embed('container', config); // Subscribe to play event embed.on('play', () => { console.log('Playback started'); }); // Subscribe to cursor position changes embed.on('cursorPosition', (position) => { console.log('Cursor moved to:', position); }); ``` *** ### off() {#off} Unsubscribe from a specific event. If no callback is provided, all listeners for the event will be removed. ```typescript off(event: EmbedEventName, callback?: () => void): void ``` **Parameters:** * `event` - `EmbedEventName` - The name of the event to unsubscribe from * `callback` *(optional)* - `() => void` - The specific callback to remove **Returns:** `void` **Example:** ```typescript const embed = new Embed('container', config); // Define a callback const playHandler = () => console.log('Playback started'); // Subscribe embed.on('play', playHandler); // Unsubscribe specific callback embed.off('play', playHandler); // Remove all listeners for an event embed.off('play'); ``` *** ## Available Events ### scoreLoaded This event is triggered once a new score has been loaded. This event doesn't include any data. ```typescript embed.on('scoreLoaded', () => { console.log('Score has been loaded'); }); ``` ### cursorPosition This event is triggered when the position of the user's cursor changes. ```typescript embed.on('cursorPosition', (position) => { console.log('Cursor position:', position); // { // "partIdx": 0, // "staffIdx": 1, // "voiceIdx": 0, // "measureIdx": 2, // "noteIdx": 1 // } }); ``` ### cursorContext This event is triggered when the position or context of the user's cursor changes. ```typescript embed.on('cursorContext', (context) => { console.log('Cursor context:', context); // { // "isRest": false, // "isGrace": false, // "isUnpitchedPart": false, // "isPitchedPart": true, // "isPitched": true, // "isChord": true, // "isTab": false, // "hasTab": true, // "hasTabFrame": false, // "isEndOfScore": false, // "isSameLineThanNextNote": false, // "hasSlashInConnection": false, // "canTieWithNextNote": false, // "canSwitchEnharmonic": false, // "isNextRest": false, // "hasTie": false, // "isHeadTied": false // } }); ``` ### measureDetails This event is triggered when the position or context of the user's cursor changes. The payload is the same as [`getMeasureDetails()`](./data.md#getmeasuredetails). ```typescript embed.on('measureDetails', (details) => { console.log('Measure details:', details); // { // "clef": { "sign": "G", "line": 2, "clef-octave-change": -1 }, // "key": { "fifths": 0 }, // "time": { "beats": 4, "beat-type": 4 }, // "displayedTime": { "beats": 4, "beat-type": 4 }, // "tempo": { "qpm": 80, "bpm": 80, "durationType": "quarter", "nbDots": 0 }, // "transpose": { "chromatic": "0" }, // "voicesData": { "voices": [0], "mainVoiceIdx": 0 } // } }); ``` ### noteDetails This event is triggered when the position or context of the user's cursor changes. The payload is the same as [`getNoteDetails()`](./data.md#getnotedetails). ```typescript embed.on('noteDetails', (details) => { console.log('Note details:', details); // { // "articulations": [], // "classicHarmony": null, // "dynamicStyle": null, // "ghostNotes": [false], // "hammerOnPullOffs": [false], // "harmony": null, // "hasArpeggio": false, // "hasGlissando": false, // "isChord": false, // "isInSlur": false, // "isRest": false, // "isTied": false, // "lines": [-2.5], // "lyrics": [], // "nbDots": 0, // "nbGraces": 0, // "ornaments": [], // "pitches": [{"step": "E", "octave": 2, "alter": 0}], // "technical": [], // "tupletType": null, // "wedgeType": null, // "durationType": "eighth" // } }); ``` ### rangeSelection This event is triggered when a range of notes is selected or the selection changed. The `noteIdx` for the `right` location is inclusive. ```typescript embed.on('rangeSelection', (selection) => { console.log('Range selection:', selection); // { // "left": { // "measureUuid": "ee882ed1-083a-3caa-34c4-cba4f0c28198", // "staffUuid": "77ce0d0c-8c09-ae97-bc58-6e8f63dffaa7", // "partUuid": "9a12babc-8397-f9d2-5da3-7688384a55cc", // "voiceUuid": "8b19453c-f6fd-c9f3-41f0-e678b002d80e", // "noteIdx": 1, // "line": 3 // }, // "right": { // "noteIdx": 2, // "measureUuid": "49fda575-db0a-065d-98a9-8214388ee8f6", // "partUuid": "1bace7c1-13e8-e513-4dbf-a28b0feaeaa3", // "staffUuid": "f03b9986-4d12-5081-c934-a6e8d6b299e3", // "voiceUuid": "862c3d23-974e-d648-6057-f8e27c585f16" // } // } }); ``` ### fullscreen This event is triggered when the fullscreen state changes. The callback receives a boolean indicating whether fullscreen is enabled. ```typescript embed.on('fullscreen', (isFullscreen) => { console.log('Fullscreen:', isFullscreen ? 'enabled' : 'disabled'); }); ``` ### embedSize This event is triggered after the score is rendered (and whenever the container resizes) to report the embed's current dimensions in pixels. ```typescript embed.on('embedSize', ({ width, height }) => { console.log(`Embed is ${width}px × ${height}px`); // Example: automatically match your container height to the score container.style.height = `${height}px`; }); ``` ### exportProgress This event is triggered during export operations ([`getMP3()`](./score-management.md#getmp3), [`getWAV()`](./score-management.md#getwav), [`getPDF()`](./score-management.md#getpdf), [`getPNG()`](./score-management.md#getpng)) to report rendering progress. The callback receives a progress object that can be used to display a progress indicator to the user. ```typescript embed.on('exportProgress', (progress) => { console.log('Export progress:', progress); }); ``` #### Example: Show export progress to the user ```typescript embed.on('exportProgress', (progress) => { progressBar.value = progress; }); const mp3Data = await embed.getMP3(); ``` ### play This event is triggered when playback starts. This event doesn't include any data. ```typescript embed.on('play', () => { console.log('Playback started'); }); ``` ### pause This event is triggered when playback is paused. This event doesn't include any data. ```typescript embed.on('pause', () => { console.log('Playback paused'); }); ``` ### stop This event is triggered when playback stops. This event doesn't include any data. ```typescript embed.on('stop', () => { console.log('Playback stopped'); }); ``` ### playbackPosition This event is triggered continuously during playback as the position changes. Useful for tracking playback progress. ```typescript embed.on('playbackPosition', (position) => { console.log('Playback position:', position); // { // currentMeasure: 3, // Index of the measure in the score // quarterFromMeasureStart: 2.2341 // Position from the beginning of the measure // } }); ``` #### Example: Get the currently playing note ```typescript const cursorPosition = await embed.getCursorPosition(); const { partUuid, voiceUuid } = cursorPosition; const measuresUuids = await embed.getMeasuresUuids(); embed.on('playbackPosition', async (playbackPosition) => { const { currentMeasure } = playbackPosition; const measureUuid = measuresUuids[currentMeasure]; const voicesUuids = await embed.getMeasureVoicesUuids({ partUuid, measureUuid, }); if (!voicesUuids.includes(voiceUuid)) { // The voice is not present in the current measure return; } const noteIdx = await embed.playbackPositionToNoteIdx({ partUuid, voiceUuid, playbackPosition, }); const noteData = await embed.getNoteData({ partUuid, measureUuid, voiceUuid, noteIdx, }); console.log('Currently playing note:', noteData); }); ``` ## Event Categories ### Score Events * `scoreLoaded` - Triggered when a score is loaded ### Cursor Events * `cursorPosition` - Cursor position changes * `cursorContext` - Cursor context changes * `measureDetails` - Measure information updates * `noteDetails` - Note information updates * `rangeSelection` - Selection range changes ### Playback Events * `play` - Playback starts * `pause` - Playback pauses * `stop` - Playback stops * `playbackPosition` - Playback position updates ### Export Events * `exportProgress` - Export rendering progress updates ### UI Events * `fullscreen` - Fullscreen state changes * `embedSize` - Embed layout dimensions change --- --- url: /developers/docs/api/authentication.md --- # Flat API Authentication The Flat Platform API uses [OAuth 2.0](https://oauth.net/2/) for authentication and authorization. If you never used OAuth2 before, we advise you to read this [great introduction](https://www.digitalocean.com/community/tutorials/an-introduction-to-oauth-2). Our API supports the **Authorization Code** and **Implicit** grants. To simplify the usage of our API for your own account, you can quickly create access tokens in your Flat account (aka. "Personal Access Tokens"). ## How to quickly getting started 1. [Create an app](https://flat.io/developers/apps) for your script or project. 2. **Try the API in 5 minutes** with [a Personal Access Token for your Flat account](#personal-access-tokens). 3. If you plan to make the app available for other people, [request some OAuth2 Credentials to our product team](https://docs.google.com/forms/d/e/1FAIpQLSeW4sZuUrcBXEtbecJ8xlWL9anbFCsrpHBgc6C48DOE4zuElQ/viewform). ## Personal Access Tokens Personal Access Tokens function like OAuth access tokens for your own account. You can generate them from your account in a few seconds: 1. [Create an app](https://flat.io/developers/apps) for your script or project 2. On the left menu, click on "**Flat API > Personal Tokens**" 3. Choose a name and the authorization scopes for your first token. That's all, you can directly use our API with this token by setting it in the `Authorization` headers of your requests: ```http Authorization: Bearer my-api-personal-access-token ``` Here is an example with cURL: ```bash curl -H 'Authorization: Bearer ' https://api.flat.io/v2/me ``` ## OAuth2 **Do you Need some OAuth2 credentials? Please [contact our product team](https://docs.google.com/forms/d/e/1FAIpQLSeW4sZuUrcBXEtbecJ8xlWL9anbFCsrpHBgc6C48DOE4zuElQ/viewform)**. Here is the main information for our OAuh2 API, you can learn more about the scopes and flows in the paragraphs below. * Authorization URL: `https://flat.io/auth/oauth` * Token URL: `https://api.flat.io/oauth/access_token` * Invalidation URL: `https://api.flat.io/oauth/invalidate_token` * [List of scopes](#scopes) ## Scopes You will need to choose and include a list of requested scopes during the OAuth flow. At this time we support the following scopes: | Scope | Description | |:------|:------------| | `account.public_profile` | Users' public profiles | | `account.email` | Access to the person's email address. | | `account.education_profile` | For education accounts, users' profiles and organization information. | | `scores.readonly` | Read-only access to all a user's scores. | | `scores.social` | Post comments and like scores | | `scores` | Full, permissive scope to access all of a user's scores. | | `collections.readonly`| Allow read-only access to a user's collections. | | `collections.add_scores` | Allow to add scores to a user's collections. | | `collections` | Full, permissive scope to access all of a user's collections. | | `notifications.readonly` | Read-only access to a user's notifications. | | `edu.resources` | Read-write access to the resource library. | | `edu.resources.readonly` | Read-only access to the resource library. | | `edu.classes` | Full, permissive scope to manage the classes. | | `edu.classes.readonly` | Read-only access to the classes. | | `edu.assignments` | Read-write access to the assignments and submissions. | | `edu.assignments.readonly` | Read-only access to the assignments and submissions. | | `edu.admin` | Full, permissive scope to manage all the admin of an organization. | | `edu.admin.lti` | Access and manage the LTI Credentials for an organization. | | `edu.admin.lti.readonly` | Read-only access to the LTI Credentials of an organization. | | `edu.admin.users` | Access and manage the users and invitations of the organization. | | `edu.admin.users.readonly` | Read-only access to the users and invitations of the organization. | | `tasks.readonly` | Read-only access to export tasks created by this account. | | `omr` | Run [Optical Music Recognition](/api/omr/) jobs and download their results. The `library` output additionally requires the `scores` scope. | ## Authorization Page Both **Authorization Code** and **Implicit** OAuth2 grants start with our authorization page. Our Authorization page (`https://flat.io/auth/oauth`) supports all the standard parameters from the **Authorization Code** grant ([RFC6749/4.1](https://tools.ietf.org/html/rfc6749#section-4.1)) and the **Implicit** grant ([RFC6749/4.2](https://tools.ietf.org/html/rfc6749#section-4.2)). The first step is to build an authorization link where you can redirect your user. Here is a simple example: ```text https://flat.io/auth/oauth?client_id=&response_type=(code|token)&state=&scope=account.public_profile+scores&redirect_uri= ``` You can find below the different parameters available, including non-standard and optional parameters. All of them can be passed as query string when redirecting the end-user to the authorization page. Property name | Required | Values and Description \---------------|----------|----------------------- `client_id` | Required | The client id (aka key) from the couple key/secret provided by Flat `response_type`| Required | We support `code` (**Authorization Code** grant, [RFC6749/4.1.1](https://tools.ietf.org/html/rfc6749#section-4.1.1)) and `token` (**Implicit**, [RFC6749/4.2.1](https://tools.ietf.org/html/rfc6749#section-4.2.1)). It is strongly advised to use the Authorization Code grant for any server-side usage and the Implicit grant for any client-side (e.g. JavaScript) usage. `scope` | Required | You must provide a list of scopes listed above and granted for your app, separated with a space. `redirect_uri` | Required | Determines where the response is sent. The value of this parameter must exactly match the value specified in your App Credentials settings. `state` | Optional | An opaque string that is round-tripped in the protocol; that is to say, it is returned as a URI parameter in the Authorization Code grant, and in the URI #fragment in the Implicit grant. `access_type` | Optional (available for the Authorization Code grant) | The acceptable values are `online` and `offline`. When specifying `offline`, the API will return a refresh token during the access token exchange. When redirecting your users to this authorization page, they will see a page that looks like the one below, where they can grant your app to access and use their account: ![Flat OAuth2 Authorization Page](/img/api-authz-page.png) ## Authorization Code grant Here is a typical flow of an **Authorization Code grant**. We advise you to use this grant for using our API in **server-side**. 1. You redirected a visitor/user to our [authorization page](#authorization-page) by specifying `response_type=code`, your `client_id` and a `redirect_uri`. 2. This user granted your app on our authorization Page. 3. Flat redirects your user back to your website at the `redirect_uri` you specified. You will receive a `code` query string with an Authorization Code that you can exchange for an access token. This URL will also include a previous `state` you specified in the authorization page URL. (e.g. `https://my-website.example.com/callback?code=&state=`) 4. To exchange this Authorization Code, use our Token API Endpoint, `https://api.flat.io/oauth/access_token` ([RFC6749/4.1.3](https://tools.ietf.org/html/rfc6749#section-4.1.3)). Here is an exchange request example (server-side): ```bash curl -i -X POST -H 'Content-Type: application/x-www-form-urlencoded' \ -d grant_type=authorization_code \ -d code= \ -d client_id= \ -d client_secret= \ -d redirect_uri= \ https://api.flat.io/oauth/access_token ``` And a response for this request: ```json { "type": "access", "token_type": "bearer", "access_token": "", "issued_at": 1492542537, "expires_in": 86400, "app": "", "appStatus": "trusted", "user": "", "scope": "account.public_profile scores" } ``` The access token is now ready to use, here is an example with cURL: ```bash curl -H 'Authorization: Bearer ' https://api.flat.io/v2/me ``` ## Implicit grant Here is a typical flow of an **Implicit grant**. We advise you to use this grant for using our API in **client-side**. We main difference with the Authorization Code grant is that you don't need to exchange a code, you directly get the access token in the URI Hash. 1. You redirected a visitor/user to our [authorization page](#authorization-page) by specifying `response_type=token`, your `client_id`, and a `redirect_uri`. 2. This user granted your app on our authorization Page. 3. Flat redirects your user back to your website at the `redirect_uri` you specified. You will receive the access token in the URI Hash (see example below). ```text https://my-website.example.com/callback#scope=account.public_profile&expires_in=86400&access_token= ``` The access token is now ready to use, here is an example with the JavaScript Fetch API: ```javascript fetch('https://api.flat.io/v2/me', { headers: { 'Authorization': 'Bearer ' + ACCESS_TOKEN } }) .then(function (response) { return response.json(); }) .then(function (me) { console.log(me); }); ``` ## Tokens revocation This OAuth2 API supports token revocation ([RFC 7009](http://tools.ietf.org/html/rfc7009)) at the following endpoint: `https://api.flat.io/oauth/invalidate_token`. --- --- url: /developers/docs/api/introduction.md description: >- Use our high-quality music and tabs notation engraving in your web sites and blogs with our customizable and interactive HTML Embed. --- # Flat Platform's REST API The Flat API allows you to easily extend the abilities of the [Flat Platform](https://flat.io), with a wide range of use cases including the following: * Creating and importing new music scores using MusicXML or MIDI files. * Browsing, updating, copying, exporting the user's scores (for example in MP3, WAV or MIDI). * Managing educational resources with [Flat for Education](https://flat.io/edu): creating & updating the organization accounts, the classes, rosters and assignments. The [schema](https://flat.io/developers/api/reference/swagger.json) of this API follows the [OpenAPI Initiative (OAI) specification](https://www.openapis.org/), you can use and work with [compatible Swagger tools](http://swagger.io/open-source-integrations/). You can also directly [browse the reference of the API online, including code samples](https://flat.io/developers/api/reference/). The Flat API is built on HTTP. Our API is RESTful It has predictable resource URLs. It returns HTTP response codes to indicate errors. It also accepts and returns JSON in the HTTP body. You can use your favorite HTTP/REST library for your programming language to use Flat's API. This specification and reference is [available on Github](https://github.com/FlatIO/api-reference). ## How to quickly get started 1. [Create an app](https://flat.io/developers/apps) for your script or project. 2. **Try the API in 5 minutes** with [a Personal Access Token for your Flat account](authentication#personal-access-tokens). 3. If you plan to make the app available for other people: * If your app will be available to all Flat consumer accounts or other Flat for Education schools, [request some OAuth2 Credentials to our product team](https://docs.google.com/forms/d/e/1FAIpQLSeW4sZuUrcBXEtbecJ8xlWL9anbFCsrpHBgc6C48DOE4zuElQ/viewform) * If you want to use our API to interact with other accounts from your [Flat for Education](https://flat.io/edu) organizations, [check our dedicated documentation](/api/flat-for-education.html). ## About this API Our whole platform and apps are based on this API, however not all the endpoints are made available publicly. Feel free to [contact us](mailto:developers@flat.io) if you have any questions, feedback or features requests. By using this API, and especially on the behalf of a user account, you must accept, respect and enforce our [Terms of Service and Privacy Policy](https://flat.io/help/en/policies). We don't offer any guarantees regading the future of this API. By using this API, you agree to update your app in a timely fashion in response to any changes that are rolled out. --- --- url: /developers/docs/api/changelog.md description: Discover the latest changes of Flat's REST API --- # Flat REST API Changelog We regularly update our API and services, you can discover all the changes to our public specification. Breaking changes are written below in bold if any. ## 2026-08-31 * Optical Music Recognition (OMR): New [FAQ section](omr/faq/) covering [credits and billing](omr/faq/credits), [limits and performance](omr/faq/limits), [recognition quality and languages](omr/faq/quality), and [commercial use, privacy, and data](omr/faq/legal). The [OMR guide](omr/) now also states that one credit is one page drawn from the same pool as the Flat apps, lists the current page, file, size, and concurrency limits alongside typical processing times, and documents commercial use of the output, our no-training-on-your-files policy, and what remains after a job is deleted. * Optical Music Recognition (OMR): The `/omr` API is out of Beta. Endpoints, fields, and behavior are now stable, and any breaking change will follow our usual deprecation process. Keeping a generic fallback for open-ended values (statuses, step and error codes) is still recommended, as new values may be added. See the [OMR API guide](omr/). ## v2.25.0 (2026-08-04) * Optical Music Recognition (OMR), **Beta API**: Take control of your jobs' data retention. `GET /omr/capabilities` now advertises `retentionDays` (30 by default), and jobs created with `output: musicxml` carry a `retention` object with their `expiryDate`. See [Retention and deletion](omr/jobs#retention-and-deletion). * `DELETE /omr/jobs/{job}` (`deleteOmrJob`): Erase a job's files and results as soon as you have collected them, instead of waiting for the deadline. The job stays listable with the `status` it finished with and records `retention.expiredDate`; downloads then return `409` (`OMR_JOB_EXPIRED`). * `GET /omr/jobs` (`listOmrJobs`): New `expired` filter, usable alongside `status`. * `GET /omr/capabilities` (`getOmrCapabilities`): Now available without authentication, so you can feature-detect before a user connects their account. Added `localesDetails`, the supported recognition languages with their English names. The fields the server always returns are now declared required, so a generated client can read them without null checks; `retentionDays` stays optional, and the account-scoped `costPerPage` and `remainingCredits` remain optional as before. * `OmrDetectedInstrument` and `OmrInstrumentOverride`: Clarified that `instrumentId` is the dotted `group.instrument` form, and documented the accepted `transposeKey` values. * Scores: * `GET /scores/{score}/revisions/{revision}/{format}` (`getScoreRevisionData`): Added `abc` export, for [ABC notation](https://abcnotation.com/). Like MIDI, this format is lossy and does not carry the full engraving of the score. * `ScoreTrack`: The `score` property is now optional. * Flat for Education: * `Assignment` and `AssignmentUpdate`: Added `freeRecord`, the configuration for Free Record assignments. * `GET /eduResources` (`listEduResources`): The `parent` documentation now points at [`listEduLibraries`](https://flat.io/developers/docs/api/reference#tag/EduResources/operation/listEduLibraries) for the library ids you can pass, rather than listing them. Which libraries an account can open depends on the account, so read them from that endpoint instead of hardcoding. * Errors: * `FlatErrorResponse`: Added `providerMessage`, a localized message from an upstream provider (for example Google Classroom) when a request fails on their side. ## v2.24.0 (2026-07-08) * Optical Music Recognition (OMR), **Beta API**: New resumable `/omr` API to import sheet music images and PDFs, with live progress and an optional interactive instrument-review step. The `/omr/jobs` endpoints cover the full job lifecycle (create, upload files, start, poll, review, export to MusicXML/MIDI, cancel), and `GET /omr/capabilities` advertises limits and credits for feature detection. Added the `omr` OAuth2 scope; importing the result into the Library (`output: library`) additionally requires `scores`. See the [OMR API guide](omr/). This API is in Beta and may change before the stable release: keep a generic fallback for open-ended values (statuses, step and error codes) and expect breaking changes to be announced. * Scores: * `POST /scores` (builder import): The instruments list now references the [Instrument IDs reference](https://flat.io/developers/docs/api/instruments) and the [`@flat/instruments`](https://www.npmjs.com/package/@flat/instruments) package for the possible `group` and `instrument` values. * Flat for Education: * `POST /organizations/{organization}/users` (`createOrganizationUser`): Added the `accountAdmin` role option (`UserCreation`). ## v2.23.0 (2026-06-16) * Asynchronous PDF import with OMR (Optical Music Recognition) — see the [Importing PDFs with OMR guide](omr/import): * `POST /scores`: Added `supportsTasks` on file imports. When set to `true` and the imported file requires OMR (e.g. a PDF), the API responds with `202 Accepted` and a `Task` reference instead of the score. Clients then poll [`GET /tasks/{task}`](https://flat.io/developers/api/reference/#operation/getTask) until the import completes. * `Task`: Added the `import-omr` task type (processes a PDF through OMR and imports it as a score). The created score identifier is available in the task's `score` property once its `state` is `done`. * `POST /scores`: The `200` response now returns the `x-flat-score-revision` and `x-flat-score-revision-date` headers. * Flat for Education: * Added the `accountAdmin` organization role (`OrganizationRole`, organization invitation creation, and the role search parameter). ## v2.22.0 (2026-04-07) * Score Import & Export - 15+ import formats documented, new `.flat` export: * `POST /scores`: Expanded the list of supported import formats with detailed documentation. **MusicXML** and **MIDI** are the preferred formats; also supported via conversion: Guitar Pro, MuseScore, ABC notation, PowerTab, Capella, MEI, Overture, TablEdit, Band-in-a-Box, Karaoke MIDI, MuseData, Score Writer, Bagpipe Music Writer, and Encore. * `GET /scores/{score}/revisions/{revision}/{format}`: Added `flat` export format for native Flat compressed files (`.flat`). * `ScoreDetails`: Added `me` property with information about the authenticated user's relationship to the score. * Collections - Simplified library navigation with virtual collections replacing the legacy folder hierarchy ([blog: Library Design Revamp](https://blog.flat.io/library-design-revamp-elevating-your-music-composition-experience/)): * New virtual collections: `allScores`, `collaborations`, and `likes` replace the deprecated `root` and `sharedWithMe` collection types. * `GET /collections` (`listCollections`): New default `parent=user` returns all user collections including virtual ones. Added `modificationDate` sort option. * `Collection`: Added `isPinned`, `labelKey`, and `modificationDate` properties. * `POST /collections/{collection}/untrash`: **Deprecated.** Collections untrashing is no longer supported. * Updated collection parameter descriptions across all endpoints to document the new virtual collections and deprecate `root`/`sharedWithMe`. * Flat for Education: * Assignments & Rubrics - Rubric grading, video/audio performance recordings, and group submissions ([blog: Performance Assignments upgrade](https://blog.flat.io/performance-assignments-just-got-an-upgrade-more-tools-flexibility/), [Grading Composition Assignments](https://blog.flat.io/how-to-grade-music-composition-assignments-without-losing-your-weekends/)): * Performance assignments: Added `recordingType` (`audio`/`video`), `allowBackingTrack`, `allowMetronome`, and `allowSpeedChange` options. * Group submissions: Added `submissionStudentsMode` (`single`/`group`) for shared writing assignments, with `assignedGroups` on `ClassAssignment`. See [blog: Introducing Shared Writing](https://blog.flat.io/collaborative-composition-flat-for-education-music-education/). * Rich text: Added `descriptionHtml` and `teacherInstructionsHtml` on assignments, `sharingDescriptionHtml` on education resources. * `ClassAttachmentCreation`: Added `partUuid`, `revision`, and `teacherOnly` properties. * Student Groups - Manage student sub-groups for shared writing and group submissions ([blog: Back to School updates](https://blog.flat.io/back-to-school-flat-for-education-updates/)): * New CRUD endpoints for student sub-groups: `GET /groups` (`listGroups`), `POST /groups` (`createGroup`), `PUT /groups/{group}` (`renameGroup`), `DELETE /groups/{group}` (`deleteGroup`). * New membership endpoints: `POST /groups/{group}/users` (`addGroupUser`), `DELETE /groups/{group}/users/{user}` (`removeGroupUser`). * Groups can be filtered by classroom or assignment, and support test student tagging (`edu:testing-students`). * New group types: `classStudentsSubGroup` and `assignmentStudentsSubGroup`. * LTI Configuration - Unified LTI 1.1 and 1.3 configuration management, replacing the previous credentials-only API ([blog: LTI 1.3 Integration](https://blog.flat.io/flat-for-education-upgrades-to-lti-1-3-for-canvas-schoology-moodle-and-blackboard/)): * New CRUD endpoints under `/organizations/lti/configurations`. * Supports LTI 1.1 manual, LTI 1.3 manual, LTI 1.3 dynamic registration, and LTI 1.3 deployment-based configurations. * Added `enableEmailMatching` option to control email-based user matching during LTI authentication. * Previous LTI 1.1 credentials endpoints (`/organizations/lti/credentials`) are now **deprecated**. LTI 1.1 configurations can now be managed through the new unified endpoints. * Score Tracks: * `GET /scores/{score}/tracks` (`listScoreTracks`): Added documentation for access control on performance submission tracks (student vs. teacher visibility). * Organization & Users - Test account management, email verification, and improved class metadata: * `GET /organizations/users` and `GET /organizations/users/count`: Added `testAccounts` filter to include/exclude test student accounts. * `UserDetailsAdmin`: Added `isEduTestingStudent` property. * `UserDetails`: Added `isEmailVerified` property. * `OrganizationInvitation`: Added `htmlUrl` with a direct join URL. * `ClassDetails`: Added `modificationDate`, and now requires `creationDate`, `name`, `state`. Updated `lti` property to cover LTI 1.1 and 1.3 context with `hasNrpsService`. * Resource Library - Rich text descriptions and assignment type selection on resource creation: * `EduResource` and `EduResourceCreation`: Added `sharingDescriptionHtml` for rich text sharing descriptions. * `EduResourceCreation`: Added `resource` property for assignment-specific creation options (e.g., assignment type). * `EduLibrary`: Renamed library type from `flatEduSamples` to `flatEduContent`. * Microsoft Teams Integration - Scheduled assignments and individual student targeting: * `MicrosoftGraphAssignment`: Added `assignDateTime` for scheduled assignments, `assignToType` (`class`/`individual`) and `assignedStudentsMsIds` for individual assignment targeting. Expanded `state` enum with `scheduled` and `inactive` statuses. * Accounts & Profiles: * `UserPublic`: Added `allPublicScoresCount` property. Removed deprecated `instruments` property. * `UserCreation`: Locale is now a free-form string (auto-normalized) instead of a strict enum. * Improved `TutteoProduct` descriptions with links to each product. * Statistics: * Added `yearly` counts to `ScoreCommentsCounts`, `ScoreLikesCounts`, `ScorePlaysCounts`, and `ScoreViewsCounts`. * Deprecations & Removals: * **Removed** `FlatLocales` enum schema, replaced by `FlatLocalesString` with auto-normalization. * **Removed** unused `billing` role from `OrganizationRoles`. * **Deprecated** `POST /collections/{collection}/untrash` (`untrashCollection`). * **Deprecated** LTI credentials endpoints in favor of the new unified configuration API. * **Deprecated** `root` and `sharedWithMe` collection parent aliases (use `user` instead). * **Deprecated** `staffIdx` on `ScoreCommentContext`. ## v2.21.0 (2024-10-18) * Scores & Library: * `GET /users/{user}/scores`: As planned in 2020, this endpoint has been updated to only return public scores for user community profiles. The endpoint has also a new pagination system and sorting options. * `ScoreDetails`: Added `editHtmlUrl`, `instrumentsNames` and `scheduledDeletionDate` properties. * `Collection`: Added `contents.scoresCount` property. * Flat Community profiles: * `UserPublic` now includes `likesCount` and `playsCount` properties. * Flat for Education: * `GET /eduResources`: * Added options `withoutSubfoldersResources`, `assignmentTypes`, `subjects`, and `grades` to filter content. * Added new response headers `X-Total-Assignments-Count` and `X-Total-Folders-Count`. * `EduResource`: Added `sharingDescription`, `subjects`, `grades` and `capabilities.canChangePrivacy` properties. * `EduResourceFolder`: Added `assignmentsTypes` and `resourcesCount` properties. * `Assignment`: Added `restrictPlayNote` and `restrictToAudioTracks` properties. * `AssignmentSubmission`: Updated LTI to support LTI 1.1 and 1.3 (`lti.gradeService` property). * `ScoreTrack`: Added `purpose` property. ## v2.20.1 (2024-03-11) * Keep `rights` property optional on `ScoreDetails` ## v2.20.0 (2024-03-08) * Accounts: * feat(account): Added pagination to `GET /users/{user}/likes` and fixed typo in operationId. * feat(account): Added `product` on `UserDetails` to know the product the user is using. * Score Library: * feat(library): Added `collaboratorType` to `ResourceRights` to know if the user accessing a resource is the owner, user or group collaborator. Adjusted non-optional properties on `ResourceRights`. * feat(library): Added `date` to `ResourceCollaborator` with the date the collaborator was added. * feat(score): Added new `mainKeySignature`, `highlightedDate` and `organization` properties to `ScoreDetails`. Adjusted non-optional properties on `ScoreDetails`. * feat(score): Added new `purpose` property to `ScoreTrack`. Adjusted non-optional properties on `ScoreTrack`. * feat(score): Added new `googleDriveDisabled` option when copying score (`POST /scores/{score}/fork`). * Flat for Education: * feat(edu): Some Flat for Education invitatons can be re-used multiple times. * fix(edu): Flat for Education invitatons can only be used to create `admin` or `teacher` accounts, fixed `organizationRole` enum. * feat(edu): Added new `verifyIfNotAlreadyInResourceLibrary` option to `POST /classes/{class}/assignments/{assignment}/copy` to avoid copying to the Resource Library if the assignment is already in it. * fix(edu): Fixed `ClassAttachmentCreation` enum values to reflect the current state of our product. * feat(edu): Added `playback` and `lti` properties to `AssignmentSubmission`. * fix(edu): `comments` object has never been available in `AssignmentSubmissionUpdate`, only in `AssignmentSubmission`. * feat(edu): Added `graded` state for submissions. * feat(edu): Added `organizationResources` library type to `GET /eduResources/libraries`, and added `organizationPublic` enum value to `EduResourcePrivacy`. * feat(edu): Added new `privacy` property to `PUT /eduResources/{resource}` * fix(edu): Removed unused property `alternateLink` from `MicrosoftGraphSubmission`. * fix(schema): missing `required: true` on some POST/PUT bodies. ## v2.19.0 (2023-08-25) * feat(edu): added new `POST /eduResources/{resource}/createLtiLink` endpoint to create LTI links from Flat for Education resources. * feat(edu): maximum graded has been increased from 100 to 10000. * feat(score): new nullable properties in `PUT /scores/{score}` to unset properties (`subtitle`, `composer`, `lyricist`, `arranger`, `description`, `creationType`, `license`, `licenseText`). * fix(score): wrong user object in `ScoreSummary`, returned object has more properties than the specification (`UserPublic`). * fix(spec): various properties marked as required as they will always be returned. ## v2.18.0 (2023-05-05) * feat(edu): Released Resource Library API in beta (`/eduResources`) with new OAuth 2 scopes `edu.resources` and `edu.resources.readonly`. * feat(edu): Updated `POST /classes/{class}/assignments/{assignment}/copy` to allow to copy to Resource Library. * feat(edu): Updated `DELETE /classes/{class}/assignments/{assignment}/submissions/{submission}` behavior, now only resets the submission instead of deleting it. * feat(edu): Added `POST /classes/{class}/testStudent` to create testing student accounts. * feat(edu): Operation `POST /classes/{class}/assignments` has been renamed from `createAssignment` -> `createClassAssignment` in schema. * feat(edu): `Assignment` models now include a new `capabilities` property returning which actions are possible with a specific resource (`canEdit`, `canPublishInClass`, `canPublishInClassError`, `canArchive`, `canUnarchive`). * feat(edu): `Assignment` models now include a new `useDedicatedAttachments` property to know if the underlying resources are dedicated and stored inside the assignment (new behavior with the resource library). * feat(edu): `ClassAssignment` now includes a new `issue` property to return any issues encountered with the assignment. * feat(edu): `toolset` id provided when creating or updated assignments will now make a copy of the toolset to have a dedicated object for the assignment. * feat(edu): `AssignmentSubmissionHistory` now includes the `source` of the change, when this one comes from a third party (Google Classroom, Microsoft Teams, LTI). It also includes the following new properties: `dueDate`, `comment` and `attachment.title`. * feat(edu): `UserDetails` now contains Microsoft Sign in details (`azureDetails`) and list of groups the user is part of (`groups`). * feat(edu): Added optional metadata on class objects (`level`, `skillsFocused`, `size`). * fix(edu): Fixed `ClassAttachmentCreation` enum values to reflect the current state of our product. * feat(scores): Updated `GET /scores/{score}/revisions/{revision}` now returns the `startDate` and `endDate` for the score revisions. * feat(scores): Updated `POST /scores` to add `hasQuarterTone` on score builders to enable quarter tones on score parts. * feat(scores): Updated `POST /scores/{score}/fork` to add option to keep original title during a file copy (`keepOriginalTitle`). * fix(schema): Added missing required properties on models `ScoreSummary`, `MediaAttachment` and `FlatErrorResponse`. ## v2.17.0 (2022-03-23) * feat(collections): Add new dedicated App Collections. When creating new scores, by default Flat will add the scores to a dedicated collection for the 3rd party app. This collection is automatically created in the user account and has a new alias `app` that can be used in the URLs paths. ## v2.16.0 (2021-12-11) * feat(scores): added `POST /scores/{score}/revisions/{revision}/{format}/task` to create a new export task for a score and `GET /tasks/{task}` to fetch the progress of an export task. ## v2.15.0 (2021-11-10) * feat(edu): added `POST /organizations/users/{user}/signinLink` to allow admins to create sign in links for their organization's users. * feat(edu): added `POST /organizations/users/{user}/accessToken` to allow admins to create delegated access tokens for their organization's users. * feat(locale): added `ja-HIRA` * feat(comments): added `moderation` object on public comments * feat(scores): added `defaultTrack` option to `GET /scores/{score}/revisions/{revision}/{format}` to return mp3 tracks when a mp3 is set as default track. * **DEPRECATED**: removed `onlyCached` option from `GET /scores/{score}/revisions/{revision}/{format}` since only cached files are now returned for audio exports. ## v2.14.0 (2021-10-04) * feat(scores): `POST /v2/scores` has a new score builder to easily create blank scores without the need of importing a MusicXML file. Provide a list of instruments to use, and optionally customize the time signature, key signature, enable TABs, Chord grids as well as the page layout. * feat(edu): `POST /v2/organizations/users` has support for roles. * feat(edu): added new `shuffleExercises` option for worksheets. * feat(edu): added new `exercisesIds` in students submissions. ## v2.13.0 (2021-07-19) * feat(scores): `GET /v2/scores/{score}/tracks` has new query strings: * `listAutoTrack` to fetch tracks automatically generated & synced (playback available as a MP3 file). * `assignment` to filter tracks related to a Flat for Education assignment. * feat(scores): added `GET /v2/scores/{score}/revisions/{revision}/synchronizationPoints` to fetch synchronization points automatically generated from latest MP3 playback file. * feat(scores): `GET /v2/scores/{score}/revisions/{revision}/{format}` has a new query string `url` to fetch the CDN URL of the exported file in the JSON body. * feat(edu): added `DELETE /v2/classes/{class}/assignments/{assignment}/submissions/{submission}` to let teachers reset students' submissions. * feat(edu): added detected `issues` on classes with the list fo accounts that couldn't be added to the classes during synchronizations. * feat(edu): added `microsoftGraph` property on assignments with the Microsoft Teams assignments `state`, URLs (`alternateLink`) and `categories`. * feat(edu): added `microsoftGraph` property on submissions with the Microsoft Teams submissions `state` and URLs (`alternateLink`). * feat(edu): `POST /v2/classes/{class}/assignments/{assignment}/copy` has a new property `scheduledDate` to schedule assignments copies. * feat(edu): added `track` property to submissions for performance assigments saved audio tracks. * feat(account): added a `coverPicture` property with the URL of the profile cover picture, and `pictureFile` and `coverPictureFile` containing the ID of the corresponding files. * feat(account): `GET /v2/me` has a new `onlyId` query string to quickly fetch current user id. ## v2.12.0 (2021-02-18) * update(scores): `ResourceCollaborator` now includes a `invited` boolean property to know if the collaborator is still a pending invite. * feat(assignments): Export grades as CSV and Excel files (`GET /classes/{class}/assignments/{assignment}/submissions/csv` and `/classes/{class}/assignments/{assignment}/submissions/excel`) * update(assignments): Assignment creation (`POST /classes/{class}/assignments`) and assignments objects now include a `type` (`AssignmentType`). * update(assignments): Assignments objects (`Assignment`) now include a cover URL (`cover`) and the corresponding file identifier (\`coverFile). * update(assignments): Assignment copy (`POST /classes/{class}/assignments/{assignment}/copy`) now accepts an optional `assigment` identifier. This can be used to override a draft assignment with the content from another assignment. * style: Lint OpenAPI v3 specification ## v2.11.0 (2020-10-26) * feat(edu): `PUT /organizations/users/{user}` has new parameters to edit accounts: `username`, `firstname`, `lastname`, `email`. * feat(edu): `POST /classes/{class}/assignments` has new parameters: * `toolset` id to enable [a toolset](https://flat.io/help/en/education/toolset.html) for the assignment. * `nbPlaybackAuthorized` to limit the number of time the playback can be used * `maxPoints` for grading purpose * `googleClassroom.topicId` to add the assignment under a specific Google Classroom course topic * `assigneeMode` and `assignedStudents` to assign specific students * `lockScoreTemplate` to lock assigned templates * `dueDate` and `scheduledDate` are nullable to unset properties * returns new information about LTI assigments, Canvas assignments and MusicFirst assignments * feat(edu): `PUT /classes/{class}/assignments/{assignment}/submissions` has: * New parameters for grading (`draftGrade`, `grade`) * A new parameter for teacher to return a submission (`return`) and * Computed comments counters (`comments`) * Returned object `AssignmentSubmission` now includes `maxPoints` for the maximum number of points when the grade was set. * feat(edu): New endpoints under `/classes/{class}/assignments/{assignment}/submissions/{submission}/comments` to create, list, update and delete comments for the submission. * update(scores): `GET /scores/{score}/revisions/{revision}/{format}` query string `parts` now only accepts parts UUIDs. * update(edu): `GET /organizations/users` query string `licenseExpirationDate` now also accepts `active` and `notActive` values, and has a new query option `onlyIds` * **DEPRECATED**: `PUT /classes/{class}/assignments/{assignment}/submissions` parameters `studentComment` and `returnFeedback` have been removed. `returnFeedback` has been replace by a boolean `return` to return a submission as a teacher. ## v2.10.0 (2020-06-03) * feat(edu): `POST /v2/organizations/users` now accepts optional `firstname` and `lastname` * update(edu): `GET /v2/organizations/users` now accepts sort options and filters * feat(edu): added `GET /v2/organizations/users/count` to count users matching specified filters * feat(edu): removed deprecated `role` property from `POST /organizations/invitations` (previously renamed to `organizationRole`) * feat(assignments): added `POST/DELETE /v2/classes/{class}/assignments/{assignment}/archive` to archive/unarchive assignments * feat(assignments): returned assignments object from `GET /v2/classes/{class}/assignments/{assignment}` now includes the main type of the assignment: `newScore`, `scoreTemplare` or `sharedWriting`. * feat(edu): users returned by `GET /v2/groups/{group}/users` can now be filtered by the sync source: `googleClassroom`, `microsoftGraph` or `clever`. * feat(scores): scores details returned by `GET /v2/scores/{score}` (and similar) now includes the audio samples list used by our playback. The `instruments` property now includes a normalized list of instruments that is not dependent from the samples used. ## v2.9.0 (2020-01-10) * Schema is now using OpenAPI 3.0.2 (previous schemas were using OpenAPI 2) * feat(scores): New metadata and update of `GET/PUT /v2/scores/{score}`: * `arranger` property has been added * `plays` statistics are now returned (`ScorePlaysCounts`) * feat(scores): New `now` proprty on the `DELETE` method to schedule a deletion to be executed shortly (avoid keeping in trash) * feat(edu): Attachments (`MediaAttachment` and `ClassAttachmentCreation`) have new type `googleDrive` for attached Drive file, and a new `googleDriveFileId` property. If the attachment is a `googleDrive` item, the `iconUrl` and `mimeType` properties are also returned * feat(edu): Add `microsoftGraph` info to `ClassDetails` (e.g. `GET /v2/classes` and `GET /v2/classes/{class}`) * feat(account): Add `firstname` and `lastname` properties for education accounts ## v2.8.0 (2019-04-27) * feat(scores): New metadata and update of `PUT /v2/scores/{score}`: * `subtitle`, `composer`, `lyricist` and `licenseText` properties has been added * when updating `title`, `subtitle`, `composer`, `lyricist` and `licenseText` via the API, the modifications events will be pushed to our real-time engine, and a new version will be scheduled (asynchronous) * `description` can now be up to 2000 characters (was previously 1000) * feat(submissions): Added education submissions states (`created`, `turnedIn`, `returned`) * feat(revisions): Return the last modification `event` when fetching a revision metadata (UUID) * feat(locale): added Turkish (`tr`) * feat(licenses): added new license source `appStore` * feat(user): added `isFlatTeam` property to public profiles * chore(specs): Inline schemas `UserInstruments`, `ResourceSharingKey`, `ScoreData`, `ScoreDataEncoding`, `CollectionTitle` ## v2.7.0 (2018-09-11) * update(spec): specify `produces` and `consumes` on endpoints instead of globally * feat(scores): now support Guitar Pro (GP3, GP4, GP5, GPX, GP), PowerTab, TuxGuitar and MuseScore files in POST /scores * feat(scores): add support for `filename` when importing scores * feat(collections): `parent` collection can now be a collection id when listing collections * feat(collections): includes parent collections when listing scores * feat(collections): add `creationDate` property in collection details * feat(comments): add `staffUuid` for contextualized comments, which will completely replace `staffIdx` in the future * feat(rights): now return a `isCollaborator` boolean property with the Score or Collection rights * update(account): added new locales supported ## v2.6.0 (2018-04-23) * feat(collections): Add new Collections API endpoints * `POST /collections`: Create new collection * `GET /collections`: List collections * `GET /collections/{collection}`: Get collection details * `PUT /collections/{collection}`: Update collection details * `DELETE /collections/{collection}`: Delete collection * `POST /collections/{collection}/untrash`: Untrash collection * `GET /collections/{collection}/scores`: List scores contained in a collection * `PUT /collections/{collection}/scores/{score}`: Add a score to a collection * `DELETE /collections/{collection}/scores/{score}`: Remove a score from a collection * feat(collections): Add new OAuth2 scopes for new features: * `collections.readonly`: Allow read-only access to a user's collections. * `collections.add_scores`: Allow to add scores to a user's collections. * `collections`: Full, permissive scope to access all of a user's collections. * feat(score): Added new method to untrash a score (`POST /v2/scores/{score}/untrash`) * feat(score): `DELETE /v2/scores/{score}` can now be used without admin rights. This new behavior will unshare the score from the current account. * feat(score): `POST /scores/{score}/fork` now accepts a collection identifier to copy a score to a specific collection. * feat(comments): Comments can now be filtered by type with the new query string `type` (`document` or `inline`). * update(openapi): Some schema definitions have been renamed, they are now used for Scores and Collections * `ScoreRights` -> `ResourceRights` * `ScoreCollaborator` -> `ResourceCollaborator` * `ScoreCollaboratorCreation` -> `ResourceCollaboratorCreation` * existing *score sharing key* -> `ResourceSharingKey` * **DEPRECATED**: `GET /scores/{score}/revisions/{revision}/{format}` no longer support part indexes for single/set of parts exports, but our own part UUIDs. * **DEPRECATED** on 2019-09-01: `GET /users/{user}/scores` will no longer list private and shared scores, but only public scores of a Flat account. ## v2.5.2 (2018-02-07) * fix(score): missing ScoreRights.aclRead type ## v2.5.1 (2018-01-16) * fix(user): Add missing escape in `pattern` (`UserCreation.username`). ## v2.5.0 (2017-10-22) * feat(scores): Add video & audio tracks support for scores: `/v2/scores/{score}/tracks`. ## v2.4.0 (2017-10-02) * feat(scores): New metadata and update of `PUT /v2/scores/{score}`: * Added metadata in API `subtitle`, `lyricist`, `composer`, `description`, `tags`, `creationType`, `license`, `licenseText`, `durationTime`, `numberMeasures`, `mainTempoQpm`, `publicationDate`. * `PUT /v2/scores/{score}`: Remove `title` property, this one can be updated by saving a new revision of the score data. * `PUT /v2/scores/{score}`: New settable properties: `description`, `tags`, `creationType`, `license`. ## v2.3.0 (2017-08-28) * feat(user): Add profile theme and instruments played. * feat(edu): Add new cursor-based pagination for `GET /v2/organizations/users` and `GET /v2/organizations/invitations`. * feat(edu): Add new methods: * `PUT /v2/organizations/users/{user}`: Admin endpoint to update managed accounts. * `DELETE /v2/organizations/users/{user}`: Admin endpoint to delete or convert edu accounts to consumer accounts. * feat(edu): Classes have a new state `inactive` that can be activated using the new method `POST /v2/classes/{class}/activate`. * feat(edu): Assignments have a new state `draft` and can have a new attachment type `exercise`. * feat(edu): Return Canvas LMS Instance domain in classes details * feat(edu): Return Clever.com section information in classes details ## v2.2.0 (2017-07-02) * feat(edu): Public release of the first education APIs: * `/v2/classes`: Classes management * `/v2/classes/{class}/assignments`: Flat Assignments and Submissions * `/v2/organizations/users`: Organization accounts management * `/v2/organizations/invitations`: Organization invitations for admins and teachers * `/v2/organizations/lti/credentials`: LTI credentials management * `/v2/groups/{group}` and `/groups/{group}/users`: List of groups and users part of groups * `/v2/scores/{score}/submissions`: Submissions linked to a score * feat(edu): New OAuth2 scopes: * `edu.classes`: Full, permissive scope to manage the classes. * `edu.classes.readonly`: Read-only access to the classes. * `edu.assignments`: Read-write access to the assignments and submissions. * `edu.assignments.readonly`: Read-only access to the assignments and submissions. * `edu.admin`: Full, permissive scope to manage all the admin of an organization. * `edu.admin.lti`: Access and manage the LTI Credentials for an organization. * `edu.admin.lti.readonly`: Read-only access to the LTI Credentials of an organization. * `edu.admin.users`: Access and manage the users and invitations of the organization. * `edu.admin.users.readonly`: Read-only access to the users and invitations of the organization. * fix(spec): Add missing scopes in specification for `GET /v2/scores/{score}/revisions/{revision}` and `GET /v2/scores/{score}/revisions/{revision}/{format}` ## v2.1.0 (2017-04-17) * feat(scores): Add support of private links sharing with `sharingKey`. * feat(comments): Make "revision" optional when creating comments and support of "last" keyword. * fix(revisions): Missing `id` property in `ScoreRevision`. * update(spec): Specify `binary` response type for `GET /v2/scores/{score}/revisions/{revision}/{format}` ## v2.0.0 (2017-04-10) * chore(api): First API public release with `/v2/me`, `/v2/scores`, `/v2/users` and `/v2/groups`. --- --- url: /developers/docs/api/errors.md --- # Flat REST API Errors In the event of an error, the response will include the relevant HTTP Status Code and a JSON object in the body with information about the error. | Property | Value | |:---------|:------| | `code` | Error code returned by the API (e.g. `CLIENT_ERROR`) | | `message` | Human readable message which describes the error | | `id` | An unique identifier (UUID) for the error. This field will be present for internal and backend errors. | ## Detailed reference on errors You can find more info about the specific errors returned for each endpoint in our [API reference](https://flat.io/developers/api/reference/). If you're having trouble with API errors, please [contact us for help](mailto:developers@flat.io). In case of a internal or backend error if you have the corresponding error unique `id` corresponding to the error, please send it to us, that can make issue diagnosis and response significantly faster. --- --- url: /developers/docs/api/sdks.md --- # Flat REST API SDKs Flat offers and maintain the following SDKs and to ease development. These SDKs are built using [Swagger Codegen](https://github.com/swagger-api/swagger-codegen), which you can also easily use to build API clients for other languages and frameworks using our [OpenAPI Specification](https://github.com/FlatIO/api-reference). ## 🐍 Python * Check out the documentation and the source code [on GitHub](https://github.com/FlatIO/api-client-python). * This SDK is available on [pypi (`flat-api`)](https://pypi.python.org/pypi/flat-api). ## 💛 Node.js and Browser * Check out the documentation and the source code [on GitHub](https://github.com/FlatIO/api-client-js). * This SDK is available on [NPM and Bower (`flat-api`)](https://www.npmjs.com/package/flat-api). ## 🐘 PHP * Check out the documentation and the source code [on GitHub](https://github.com/FlatIO/api-client-php). * This SDK is available on [Packagist (`flat/api`)](https://packagist.org/packages/flat/api). ## 💎 Ruby * Check out the documentation and the source code [on GitHub](https://github.com/FlatIO/api-client-ruby). * This SDK is available on [Rubygems (`flat_api`)](https://rubygems.org/gems/flat_api). --- --- url: /developers/docs/embed/getting-started.md description: Discover how to quickly get started with our Sheet music embed. --- # Getting started with our Music engraving Embed The easiest way to get started with our [Sheet Music embed](https://flat.io/embed) is to use our [code generator](https://flat.io/developers/embed/generator). This one will build the basic HTML code for your embed and let you custom the most common [url parameters](url-parameters). You can quickly access to the generator from any sheet music hosted on Flat: click on the "Share" button on the top right of the editor, then click on "Embed". If the score is private, a private sharing link with a `sharingKey` will be generated for the document: ![Get started with our Sheet Music Embed Generator](/img/share-embed-generator.gif) You will get a similar code that you can paste to your web page code or blog post code: ```html ``` The attribute `allowfullscreen` will allow your visitors to open the score in fullscreen. You can also add extra URL parameters to customize your music score or embed appearance, discover them in [the related documentation](url-parameters). --- --- url: /developers/docs/import/assets.md description: You can find here the assets you may need to integrate our APIs. --- # Graphic assets You can find below different graphic assets you can use to integrate Flat. Please [contact us](mailto:developers@flat.io) if you need more resources. ## Edit with Flat | Preview | URLs | |---------|------| | ![Edit with Flat (White)](https://flat.io/img/assets/edit-with-flat-white.svg) | **SVG**: **PNG**: | | ![Edit with Flat (Blue)](https://flat.io/img/assets/edit-with-flat-blue.svg) | **SVG**: **PNG**: | ## Add to Flat | Preview | URLs | |---------|------| | ![Add to Flat (White)](https://flat.io/img/assets/add-to-flat-white.svg) | **SVG**: **PNG**: | | ![Add to Flat (Blue)](https://flat.io/img/assets/add-to-flat-blue.svg) | **SVG**: **PNG**: | --- --- url: /developers/docs/embed/usage-billing.md --- # How your usage is billed in Flat Embed? Our [Embed Pro plan](https://flat.io/embed) operates on a usage-based billing model. Charges are determined by the number of unique monthly users who access the Flat Embed on your website. For detailed information on our pricing structure, visit our [pricing page](https://flat.io/embed#pricing). If you're an existing Embed subscriber, you can monitor your usage on the [Embed billing page](https://flat.io/developers/apps/_/embed/billing). **Legacy Plans**: For those subscribed to Legacy embed plans prior to 2024, billing is twofold. Viewer traffic is billed based on the total page views, while editor traffic is calculated according to the number of users. In the following sections, we will explore how unique user interactions with your embed are counted, and provide guidance on configuring your embed to accurately track usage. ## Recommended Approach: Utilizing a Unique User Identifier For precise billing based on your traffic, we recommend providing an opaque user identifier (`userId`) each time the embed is loaded. Consider a practical example: Suppose "Pierre" is a user in your database with the unique identifier `42`. Each time Pierre accesses a page on your website that contains an embed, you should pass this `userId` within the [embed URLs](/embed/url-parameters). When incorporating `", "thumbnail_url": "https://flat.io/api/v2/scores/56ae21579a127715a02901a6/revisions/last/thumbnail.png" } ``` XML Example: ```bash $ curl "https://flat.io/services/oembed?format=xml&url=https%3A%2F%2Fflat.io%2Fscore%2F56ae21579a127715a02901a6" 1.0 House of the Rising Sun rich 800 400 <iframe src="https://flat.io/embed/56ae21579a127715a02901a6?" allowfullscreen height="400" width="800" frameBorder="0"></iframe> Flat Team https://flat.io/flat Flat https://flat.io https://flat.io/api/v2/scores/56ae21579a127715a02901a6/revisions/last/thumbnail.png ``` ## oEmbed Parameters We support all the following standard parameters: | Parameters | Required | Description | Default value | |:-----------|:---------|-------------|---------------| | `url` | required | The URL of the sheet music to be embedded || | `format` | optional | The returned format (`json` and `xml` are supported) | `json` | | `maxwidth` | optional | The maximum width of a rendered score in whole pixels. This value must be at least `100`, otherwise the width will be 100px. | `800` | | `maxheight` | optional | The maximum height of a rendered score in whole pixels. This value must be at least `100`, otherwise the width will be 100px. | `400` ## Custom [Embed URL Parameters](url-parameters) If extra query parameters are specified in the oEmbed request or in the URL you are retrieving embedding information from, they will be passed to the final embed URL. This allows you to easily use all of your [Embed URL Parameters](url-parameters). ```text https://flat.io/services/oembed?format=json&url=https%3A%2F%2Fflat.io%2Fscore%2F56ae21579a127715a02901a6&layout=track https://flat.io/services/oembed?format=json&url=https%3A%2F%2Fflat.io%2Fscore%2F56ae21579a127715a02901a6%3Flayout%3Dtrack ``` --- --- url: /developers/docs/api/reference.md --- --- --- url: /developers/docs/api/flat-for-education.md --- # Using our APIs with Flat for Education Our REST API is the perfect solution to interact with your Flat for Education accounts and extend the capabilities of our platform. Let's discover on this page how to take full advantage of its features. In this page: * [Available features in the API](#available-features-in-the-api) * [Your first steps with our REST API](#your-first-steps-with-our-rest-api) * [Interacting with other teachers and students' accounts](#interacting-with-other-teachers-and-students-accounts) * [Search user account ID](#search-user-account-id) * [Create access token for your end-user](#create-access-token-for-your-end-user) * [Use the delegated access token](#use-the-delegated-access-token) * [Creating Sign-in links](#creating-sign-in-links) * [Search user account ID](#search-user-account-id-1) * [New sign-in link](#new-sign-in-link) Any questions? Please contact our team at . ## Available features in the API Our web and mobile applications use the same API we make available to our customers, which means most of our platform features can be used programmatically. For example: * [Creating a new score or import a new score file](https://flat.io/developers/api/reference/#operation/createScore) in a user account. * [Creating](https://flat.io/developers/api/reference/#operation/createOrganizationUser), [managing](https://flat.io/developers/api/reference/#operation/listOrganizationUsers), and [deleting](https://flat.io/developers/api/reference/#operation/removeOrganizationUser) students and teachers accounts. * [Creating](https://flat.io/developers/api/reference/#operation/createClass), [accessing](https://flat.io/developers/api/reference/#operation/listClasses) classes, and [managing rostering](https://flat.io/developers/api/reference/#operation/addClassUser). * [Creating](https://flat.io/developers/api/reference/#operation/createAssignment) assignments, [submitting them as students](https://flat.io/developers/api/reference/#operation/createSubmission), and [exporting grades](https://flat.io/developers/api/reference/#operation/exportSubmissionsReviewsAsCsv). Let's discover below how to get started with our API. ## Your first steps with our REST API To get started with our Flat for Education API: 1. If you do not have a Flat for Education school account, [create one on our website](https://flat.io/edu). 2. Using your education account, [register a new app](https://flat.io/developers/apps). Then on the left menu, choose **"Flat API > Personal Tokens"**. Choose a name and the authorization scopes for your first token. That's all, you can directly use our API with this token by setting it in the `Authorization` headers of your requests: ```http Authorization: Bearer my-api-personal-access-token ``` Here is an example with cURL: ```bash curl -H 'Authorization: Bearer ' \ https://api.flat.io/v2/me ``` ## Interacting with other teachers and students' accounts Our education REST API includes an endpoint that lets you create delegated access tokens. These tokens let you interact with our product as another teachers or students without any user interaction required. For example, you could automatically create classes or assignments for your teachers or create or upload scores in your students' accounts. Once you created a student or teacher account whether [with our interface](https://flat.io/help/en/education/invite-students.html) or [our API](https://flat.io/developers/api/reference/#operation/createOrganizationUser), [create a personal access token](https://flat.io/developers/apps) as explained above with the `edu.admin.users` authorization. For the following examples, let's set our token in a shell variable ```bash export TOKEN=my-api-personal-access-token ``` ### Search user account ID If you do not know the unique identifier of the student/teacher account, you can use the [`GET /v2/organizations/users`](https://flat.io/developers/api/reference/#operation/listOrganizationUsers) API method to search it: ```bash curl 'https://api.flat.io/v2/organizations/users?q=student42@gedu.demo.flat.io' \ -H "Authorization: Bearer $TOKEN" ``` ```json [ { "id": "STUDENT_USER_ID", "type": "user", "organizationRole": "user", "classRole": "student", "username": "tony", ... } ] ``` ### Create access token for your end-user Now create an access token for this student using [your admin API endpoint `POST /v2/organizations/users/{user}/accessToken`](https://flat.io/developers/api/reference/#operation/createOrganizationUserAccessToken). For example with the `scores` authorization scope to be able to create new scores in the student's account and `collections` to access to their library: ```bash curl -X POST 'https://api.flat.io/v2/organizations/users/STUDENT_USER_ID/accessToken' \ -H "Authorization: Bearer $TOKEN" \ -H 'Content-Type: application/json' \ -d '{"scopes": ["scores", "collections"]}' ``` ```json { "id": "61a4bc9750724f0013fdc7fd", "name": "Access token created by organization admin", "token": "An access token for your student account", "issuedDate": "2021-11-29T11:42:15.475Z", "expirationDate": "2021-11-30T11:42:15.475Z", "scopes": [ "scores", "collections" ] } ``` ### Use the delegated access token With the newly created access token, you can interact with the end-user account without any user interaction needed. For example, you can list your student library: ```bash export STUDENT_TOKEN=student-access-token curl 'https://api.flat.io/v2/collections/root/scores' \ -H "Authorization: Bearer $STUDENT_TOKEN" ``` ```json [ { "id": "615adeb58e4ed600136ab31d", "title": "My first assignment - Tony Morris", "privacy": "private", .... }, .... ] ``` ## Creating Sign-in links Our education REST API includes an endpoint that lets you create sign in links for your users. They can typically be used to redirect your end-users to our platform while connecting them. Once you created a student or teacher account whether [with our interface](https://flat.io/help/en/education/invite-students.html) or [our API](https://flat.io/developers/api/reference/#operation/createOrganizationUser), [create a personal access token](https://flat.io/developers/apps) as explained above with the `edu.admin.users` authorization. For the following examples, let's set our token in a shell variable ```bash export TOKEN=my-api-personal-access-token ``` ### Search user account ID If you do not know the unique identifier of the student/teacher account, you can use the [`GET /v2/organizations/users`](https://flat.io/developers/api/reference/#operation/listOrganizationUsers) API method to search it: ```bash curl 'https://api.flat.io/v2/organizations/users?q=student42@gedu.demo.flat.io' \ -H "Authorization: Bearer $TOKEN" ``` ```json [ { "id": "STUDENT_USER_ID", "type": "user", "organizationRole": "user", "classRole": "student", "username": "tony", ... } ] ``` ### New sign-in link Now create a sign in link for this end-user using [your admin API endpoint `POST /v2/organizations/users/{user}/signinLink`](https://flat.io/developers/api/reference/#operation/createOrganizationUserSigninLink): ```bash curl -X POST 'https://api.flat.io/v2/organizations/users/STUDENT_USER_ID/signinLink' \ -H "Authorization: Bearer $TOKEN" \ -H 'Content-Type: application/json' \ -d '{}' ``` ```json { "url": "https://flat.io/auth/signin-link/xxxxxxxxxxxxxxxxxxx?next=%2F", "expirationDate": "2021-11-30T13:12:09.783Z" } ``` The returned URL can be used once by your end-user to sign in. We recommand to use it in a HTTP Temporary Redirect ([302](https://en.wikipedia.org/wiki/HTTP_302)). Optionally you can provide a [`destinationPath`](https://flat.io/developers/api/reference/#operation/createOrganizationUserSigninLink), for example, to redirect the user to a specific assignment or score once logged in. ## Discover the API Check out [our API reference to learn more](https://flat.io/developers/api/reference/) about the REST API possibilities: * [Scores](https://flat.io/developers/api/reference/#tag/Score) and [library collections](https://flat.io/developers/api/reference/#tag/Collection) * [Flat for Education accounts management](https://flat.io/developers/api/reference/#operation/listOrganizationUsers) * [Classes](https://flat.io/developers/api/reference/#operation/listClasses) and [assignments](https://flat.io/developers/api/reference/#operation/listAssignments). Do you have some feedback about our product and APIs? Please contact our product team at .