···11+{
22+ "lexicon": 1,
33+ "id": "fm.teal.alpha.actor.profile",
44+ "defs": {
55+ "main": {
66+ "type": "record",
77+ "description": "This lexicon is in a not officially released state. It is subject to change. | A declaration of a teal.fm account profile.",
88+ "key": "literal:self",
99+ "record": {
1010+ "type": "object",
1111+ "properties": {
1212+ "displayName": {
1313+ "type": "string",
1414+ "maxGraphemes": 64,
1515+ "maxLength": 640
1616+ },
1717+ "description": {
1818+ "type": "string",
1919+ "description": "Free-form profile description text.",
2020+ "maxGraphemes": 256,
2121+ "maxLength": 2560
2222+ },
2323+ "descriptionFacets": {
2424+ "type": "array",
2525+ "description": "Annotations of text in the profile description (mentions, URLs, hashtags, etc).",
2626+ "items": { "type": "ref", "ref": "app.bsky.richtext.facet" }
2727+ },
2828+ "featuredItem": {
2929+ "type": "ref",
3030+ "description": "The user's most recent item featured on their profile.",
3131+ "ref": "#featuredItem"
3232+ },
3333+ "avatar": {
3434+ "type": "blob",
3535+ "description": "Small image to be displayed next to posts from account. AKA, 'profile picture'",
3636+ "accept": ["image/png", "image/jpeg"],
3737+ "maxSize": 1000000
3838+ },
3939+ "banner": {
4040+ "type": "blob",
4141+ "description": "Larger horizontal image to display behind profile view.",
4242+ "accept": ["image/png", "image/jpeg"],
4343+ "maxSize": 1000000
4444+ },
4545+ "createdAt": { "type": "string", "format": "datetime" }
4646+ }
4747+ }
4848+ },
4949+ "featuredItem": {
5050+ "type": "object",
5151+ "required": ["mbid", "type"],
5252+ "properties": {
5353+ "mbid": {
5454+ "type": "string",
5555+ "description": "The Musicbrainz ID of the item"
5656+ },
5757+ "type": {
5858+ "type": "string",
5959+ "description": "The type of the item. Must be a valid Musicbrainz type, e.g. album, track, recording, etc."
6060+ }
6161+ }
6262+ }
6363+ }
6464+}
+52
lexicons/teal/actor/searchActors.json
···11+{
22+ "lexicon": 1,
33+ "id": "fm.teal.alpha.actor.searchActors",
44+ "description": "This lexicon is in a not officially released state. It is subject to change. | Searches for actors based on profile contents.",
55+ "defs": {
66+ "main": {
77+ "type": "query",
88+ "parameters": {
99+ "type": "params",
1010+ "required": ["q"],
1111+ "properties": {
1212+ "q": {
1313+ "type": "string",
1414+ "description": "The search query",
1515+ "maxGraphemes": 128,
1616+ "maxLength": 640
1717+ },
1818+ "limit": {
1919+ "type": "integer",
2020+ "description": "The maximum number of actors to return",
2121+ "minimum": 1,
2222+ "maximum": 25
2323+ },
2424+ "cursor": {
2525+ "type": "string",
2626+ "description": "Cursor for pagination"
2727+ }
2828+ }
2929+ },
3030+ "output": {
3131+ "encoding": "application/json",
3232+ "schema": {
3333+ "type": "object",
3434+ "required": ["actors"],
3535+ "properties": {
3636+ "actors": {
3737+ "type": "array",
3838+ "items": {
3939+ "type": "ref",
4040+ "ref": "fm.teal.alpha.actor.defs#miniProfileView"
4141+ }
4242+ },
4343+ "cursor": {
4444+ "type": "string",
4545+ "description": "Cursor for pagination"
4646+ }
4747+ }
4848+ }
4949+ }
5050+ }
5151+ }
5252+}
+31
lexicons/teal/actor/status.json
···11+{
22+ "lexicon": 1,
33+ "id": "fm.teal.alpha.actor.status",
44+ "defs": {
55+ "main": {
66+ "type": "record",
77+ "description": "This lexicon is in a not officially released state. It is subject to change. | A declaration of the status of the actor. Only one can be shown at a time. If there are multiple, the latest record should be picked and earlier records should be deleted or tombstoned.",
88+ "key": "literal:self",
99+ "record": {
1010+ "type": "object",
1111+ "required": ["time", "item"],
1212+ "properties": {
1313+ "time": {
1414+ "type": "string",
1515+ "format": "datetime",
1616+ "description": "The unix timestamp of when the item was recorded"
1717+ },
1818+ "expiry": {
1919+ "type": "string",
2020+ "format": "datetime",
2121+ "description": "The unix timestamp of the expiry time of the item. If unavailable, default to 10 minutes past the start time."
2222+ },
2323+ "item": {
2424+ "type": "ref",
2525+ "ref": "fm.teal.alpha.feed.defs#playView"
2626+ }
2727+ }
2828+ }
2929+ }
3030+ }
3131+}
+82
lexicons/teal/feed/defs.json
···11+{
22+ "lexicon": 1,
33+ "id": "fm.teal.alpha.feed.defs",
44+ "description": "This lexicon is in a not officially released state. It is subject to change. | Misc. items related to feeds.",
55+ "defs": {
66+ "playView": {
77+ "type": "object",
88+ "required": ["trackName", "artistNames"],
99+ "properties": {
1010+ "trackName": {
1111+ "type": "string",
1212+ "minLength": 1,
1313+ "maxLength": 256,
1414+ "maxGraphemes": 2560,
1515+ "description": "The name of the track"
1616+ },
1717+ "trackMbId": {
1818+ "type": "string",
1919+ "description": "The Musicbrainz ID of the track"
2020+ },
2121+ "recordingMbId": {
2222+ "type": "string",
2323+ "description": "The Musicbrainz recording ID of the track"
2424+ },
2525+ "duration": {
2626+ "type": "integer",
2727+ "description": "The length of the track in seconds"
2828+ },
2929+ "artistNames": {
3030+ "type": "array",
3131+ "items": {
3232+ "type": "string",
3333+ "minLength": 1,
3434+ "maxLength": 256,
3535+ "maxGraphemes": 2560
3636+ },
3737+ "description": "Array of artist names in order of original appearance."
3838+ },
3939+ "artistMbIds": {
4040+ "type": "array",
4141+ "items": {
4242+ "type": "string"
4343+ },
4444+ "description": "Array of Musicbrainz artist IDs"
4545+ },
4646+ "releaseName": {
4747+ "type": "string",
4848+ "maxLength": 256,
4949+ "maxGraphemes": 2560,
5050+ "description": "The name of the release/album"
5151+ },
5252+ "releaseMbId": {
5353+ "type": "string",
5454+ "description": "The Musicbrainz release ID"
5555+ },
5656+ "isrc": {
5757+ "type": "string",
5858+ "description": "The ISRC code associated with the recording"
5959+ },
6060+ "originUrl": {
6161+ "type": "string",
6262+ "description": "The URL associated with this track"
6363+ },
6464+ "musicServiceBaseDomain": {
6565+ "type": "string",
6666+ "description": "The base domain of the music service. e.g. music.apple.com, tidal.com, spotify.com. Defaults to 'local' if not provided."
6767+ },
6868+ "submissionClientAgent": {
6969+ "type": "string",
7070+ "maxLength": 256,
7171+ "maxGraphemes": 2560,
7272+ "description": "A user-agent style string specifying the user agent. e.g. tealtracker/0.0.1b (Linux; Android 13; SM-A715F). Defaults to 'manual/unknown' if not provided."
7373+ },
7474+ "playedTime": {
7575+ "type": "string",
7676+ "format": "datetime",
7777+ "description": "The unix timestamp of when the track was played"
7878+ }
7979+ }
8080+ }
8181+ }
8282+}
+45
lexicons/teal/feed/getActorFeed.json
···11+{
22+ "lexicon": 1,
33+ "id": "fm.teal.alpha.feed.getActorFeed",
44+ "description": "This lexicon is in a not officially released state. It is subject to change. | Retrieves multiple plays from the index or via an author's DID.",
55+ "defs": {
66+ "main": {
77+ "type": "query",
88+ "parameters": {
99+ "type": "params",
1010+ "required": ["authorDID"],
1111+ "properties": {
1212+ "authorDID": {
1313+ "type": "string",
1414+ "format": "at-identifier",
1515+ "description": "The author's DID for the play"
1616+ },
1717+ "cursor": {
1818+ "type": "string",
1919+ "description": "The cursor to start the query from"
2020+ },
2121+ "limit": {
2222+ "type": "integer",
2323+ "description": "The upper limit of tracks to get per request. Default is 20, max is 50."
2424+ }
2525+ }
2626+ },
2727+ "output": {
2828+ "encoding": "application/json",
2929+ "schema": {
3030+ "type": "object",
3131+ "required": ["plays"],
3232+ "properties": {
3333+ "plays": {
3434+ "type": "array",
3535+ "items": {
3636+ "type": "ref",
3737+ "ref": "fm.teal.alpha.feed.defs#playView"
3838+ }
3939+ }
4040+ }
4141+ }
4242+ }
4343+ }
4444+ }
4545+}
+38
lexicons/teal/feed/getPlay.json
···11+{
22+ "lexicon": 1,
33+ "id": "fm.teal.alpha.feed.getPlay",
44+ "description": "This lexicon is in a not officially released state. It is subject to change. | Retrieves a play given an author DID and record key.",
55+ "defs": {
66+ "main": {
77+ "type": "query",
88+ "parameters": {
99+ "type": "params",
1010+ "required": ["authorDID", "rkey"],
1111+ "properties": {
1212+ "authorDID": {
1313+ "type": "string",
1414+ "format": "at-identifier",
1515+ "description": "The author's DID for the play"
1616+ },
1717+ "rkey": {
1818+ "type": "string",
1919+ "description": "The record key of the play"
2020+ }
2121+ }
2222+ },
2323+ "output": {
2424+ "encoding": "application/json",
2525+ "schema": {
2626+ "type": "object",
2727+ "required": ["play"],
2828+ "properties": {
2929+ "play": {
3030+ "type": "ref",
3131+ "ref": "fm.teal.alpha.feed.defs#playView"
3232+ }
3333+ }
3434+ }
3535+ }
3636+ }
3737+ }
3838+}
+87
lexicons/teal/feed/play.json
···11+{
22+ "lexicon": 1,
33+ "id": "fm.teal.alpha.feed.play",
44+ "description": "This lexicon is in a not officially released state. It is subject to change. | A declaration of a teal.fm play. Plays are submitted as a result of a user listening to a track. Plays should be marked as tracked when a user has listened to the entire track if it's under 2 minutes long, or half of the track's duration up to 4 minutes, whichever is longest.",
55+ "defs": {
66+ "main": {
77+ "type": "record",
88+ "key": "tid",
99+ "record": {
1010+ "type": "object",
1111+ "required": ["trackName", "artistNames"],
1212+ "properties": {
1313+ "trackName": {
1414+ "type": "string",
1515+ "minLength": 1,
1616+ "maxLength": 256,
1717+ "maxGraphemes": 2560,
1818+ "description": "The name of the track"
1919+ },
2020+ "trackMbId": {
2121+ "type": "string",
2222+2323+ "description": "The Musicbrainz ID of the track"
2424+ },
2525+ "recordingMbId": {
2626+ "type": "string",
2727+ "description": "The Musicbrainz recording ID of the track"
2828+ },
2929+ "duration": {
3030+ "type": "integer",
3131+ "description": "The length of the track in seconds"
3232+ },
3333+ "artistNames": {
3434+ "type": "array",
3535+ "items": {
3636+ "type": "string",
3737+ "minLength": 1,
3838+ "maxLength": 256,
3939+ "maxGraphemes": 2560
4040+ },
4141+ "description": "Array of artist names in order of original appearance."
4242+ },
4343+ "artistMbIds": {
4444+ "type": "array",
4545+ "items": {
4646+ "type": "string"
4747+ },
4848+ "description": "Array of Musicbrainz artist IDs"
4949+ },
5050+ "releaseName": {
5151+ "type": "string",
5252+ "maxLength": 256,
5353+ "maxGraphemes": 2560,
5454+ "description": "The name of the release/album"
5555+ },
5656+ "releaseMbId": {
5757+ "type": "string",
5858+ "description": "The Musicbrainz release ID"
5959+ },
6060+ "isrc": {
6161+ "type": "string",
6262+ "description": "The ISRC code associated with the recording"
6363+ },
6464+ "originUrl": {
6565+ "type": "string",
6666+ "description": "The URL associated with this track"
6767+ },
6868+ "musicServiceBaseDomain": {
6969+ "type": "string",
7070+ "description": "The base domain of the music service. e.g. music.apple.com, tidal.com, spotify.com. Defaults to 'local' if unavailable or not provided."
7171+ },
7272+ "submissionClientAgent": {
7373+ "type": "string",
7474+ "maxLength": 256,
7575+ "maxGraphemes": 2560,
7676+ "description": "A metadata string specifying the user agent where the format is `<app-identifier>/<version> (<kernel/OS-base>; <platform/OS-version>; <device-model>)`. If string is provided, only `app-identifier` and `version` are required. `app-identifier` is recommended to be in reverse dns format. Defaults to 'manual/unknown' if unavailable or not provided."
7777+ },
7878+ "playedTime": {
7979+ "type": "string",
8080+ "format": "datetime",
8181+ "description": "The unix timestamp of when the track was played"
8282+ }
8383+ }
8484+ }
8585+ }
8686+ }
8787+}