---
title: "Ajouter une chanson a mon carnet"
method: POST
path: "/me/songs"
tags: ["carnet"]
---

# Ajouter une chanson a mon carnet

`POST /me/songs`

## Request

- Base URL: `https://jam-jam.org/api/v1`
- URL: `https://jam-jam.org/api/v1/me/songs`
- Auth: one of:
  - HTTP bearer
  - none

Ajoute une chanson au carnet PRIVE de l'appelant. Le corps porte le
payload pivot canonique, exactement l'objet rendu par
`GET /jobs/{id}/result/songbook` (`songs[0]`) ou par
`GET /me/songs/{songId}` (`song`) : convertir puis ranger au carnet
est donc un copier-coller, sans transformation.

IDENTIFIANT : il est DERIVE, jamais tire au sort. Dans l'ordre,
`song.id` s'il est fourni, sinon le slug `artiste-titre` (la meme
derivation que l'import dans l'application). Consequence utile :
reposter deux fois la meme chanson REMPLACE la premiere au lieu de
creer un doublon, et rend `200` plutot que `201`.

PUBLICATION : un ajout ne publie JAMAIS sur le profil. Publier est
une declaration explicite, une fois par objet ; elle se fait par
`PATCH /me/songs/{songId}` avec `publish` et `publishDeclaration`.

IDEMPOTENCE : poser `Idempotency-Key` est recommande. Un rejeu EXACT
(meme cle, meme corps) rend la MEME reponse en `200`, sans consommer
une seconde unite de quota ; la meme cle avec un corps different rend
`422 idempotency-conflict`.

Consomme UNE unite du compteur d'ECRITURE (`write` dans
`GET /me/usage`), jamais une conversion ni une lecture.

## Headers

- `Idempotency-Key` string

## Request body

- SongUpsert: Corps de `POST /me/songs` et de `PUT /me/songs/{songId}`. Un champ INCONNU est REFUSE (`400`), jamais retire en silence : un client qui se trompe de nom doit l'apprendre, pas croire qu'il a ete pris en compte.
  - `song` object, required: Payload pivot canonique. La meme forme que `songs[0]` de `GET /jobs/{id}/result/songbook` et que `song` de `GET /me/songs/{songId}` : `title` (obligatoire, non vide), `artist`, `sections[].lines[].lyrics` et `.chords[] = { offset, chord }`, `detectedKey { tonic, scale }`, `metadata { capo, bpm, ... }`. Validee par la MEME porte que l'import d'un fichier `.jamsong` dans l'application ; une forme invalide rend `422 unprocessable-entity` avec le motif en clair. Plafond DUR de 512 Ko (JSON serialise), sinon `413 payload-too-large`.
  - `playlistIds` string[]: Etat CIBLE COMPLET des appartenances. La chanson est ajoutee aux playlists citees et RETIREE de toutes les autres. Omis = les appartenances ne bougent pas.
  - `publish` boolean: Reserve : une CREATION ne publie jamais par defaut. Publier passe par `PATCH`, avec `publishDeclaration`.
  - `publishDeclaration` 'created' | 'imported_no_known_restriction' | 'arrangement'

## Response `200`

Chanson REMPLACEE (l'identifiant derive existait deja), ou rejeu
idempotent d'une creation precedente.

- WriteAck: Accuse d'ecriture, identique sur les six routes qui en rendent un. Volontairement MINIMAL : l'identifiant pour adresser l'objet, et l'horodatage a renvoyer en `If-Match` a la prochaine ecriture. Relire l'objet complet se fait par `GET /me/songs/{songId}`, qui consomme du quota de LECTURE : ne pas l'imposer a chaque ecriture est delibere.
  - `id` string, required: Identifiant stable de l'objet ecrit.
  - `updatedAt` string, date-time, required: Horodatage serveur apres l'ecriture, en ISO 8601 UTC au millieme. C'est EXACTEMENT la valeur a renvoyer dans `If-Match`.
  - `published` boolean: Present UNIQUEMENT quand la requete portait `publish` : etat REEL de la publication apres l'ecriture. Un refus de publication n'est jamais un `published: false` silencieux, c'est un `409`.

## Other responses

- `201`: Chanson creee
- `400`: Toute erreur de cette API, quel que soit le code HTTP, est un `application/problem+json` (RFC 9457) avec ce meme schema : `code` est la valeur stable a tester par un client (le `status` HTTP peut varier legerement selon le contexte, `code` non). `quota` est renseigne pour les erreurs liees au quota (`quota-exhausted`, `anon-quota-exhausted`, `client-quota`).
- `401`: Toute erreur de cette API, quel que soit le code HTTP, est un `application/problem+json` (RFC 9457) avec ce meme schema : `code` est la valeur stable a tester par un client (le `status` HTTP peut varier legerement selon le contexte, `code` non). `quota` est renseigne pour les erreurs liees au quota (`quota-exhausted`, `anon-quota-exhausted`, `client-quota`).
- `403`: Toute erreur de cette API, quel que soit le code HTTP, est un `application/problem+json` (RFC 9457) avec ce meme schema : `code` est la valeur stable a tester par un client (le `status` HTTP peut varier legerement selon le contexte, `code` non). `quota` est renseigne pour les erreurs liees au quota (`quota-exhausted`, `anon-quota-exhausted`, `client-quota`).
- `409`: Toute erreur de cette API, quel que soit le code HTTP, est un `application/problem+json` (RFC 9457) avec ce meme schema : `code` est la valeur stable a tester par un client (le `status` HTTP peut varier legerement selon le contexte, `code` non). `quota` est renseigne pour les erreurs liees au quota (`quota-exhausted`, `anon-quota-exhausted`, `client-quota`).
- `413`: Toute erreur de cette API, quel que soit le code HTTP, est un `application/problem+json` (RFC 9457) avec ce meme schema : `code` est la valeur stable a tester par un client (le `status` HTTP peut varier legerement selon le contexte, `code` non). `quota` est renseigne pour les erreurs liees au quota (`quota-exhausted`, `anon-quota-exhausted`, `client-quota`).
- `415`: Toute erreur de cette API, quel que soit le code HTTP, est un `application/problem+json` (RFC 9457) avec ce meme schema : `code` est la valeur stable a tester par un client (le `status` HTTP peut varier legerement selon le contexte, `code` non). `quota` est renseigne pour les erreurs liees au quota (`quota-exhausted`, `anon-quota-exhausted`, `client-quota`).
- `422`: Toute erreur de cette API, quel que soit le code HTTP, est un `application/problem+json` (RFC 9457) avec ce meme schema : `code` est la valeur stable a tester par un client (le `status` HTTP peut varier legerement selon le contexte, `code` non). `quota` est renseigne pour les erreurs liees au quota (`quota-exhausted`, `anon-quota-exhausted`, `client-quota`).
- `429`: Toute erreur de cette API, quel que soit le code HTTP, est un `application/problem+json` (RFC 9457) avec ce meme schema : `code` est la valeur stable a tester par un client (le `status` HTTP peut varier legerement selon le contexte, `code` non). `quota` est renseigne pour les erreurs liees au quota (`quota-exhausted`, `anon-quota-exhausted`, `client-quota`).

---

[API](https://skmtc.dev/jam-jam/apis/jam-jam-convert-api.md) · [All operations](https://skmtc.dev/jam-jam/apis/jam-jam-convert-api/llms.txt) · [OpenAPI document](https://skmtc.dev/jam-jam/apis/jam-jam-convert-api/revisions/64cd41a46e4e?raw)
