API reference / Documentation

OpenAPI reference

Endpoints, parameters, responses, and schemas generated from the SongCollect OpenAPI specification.

This reference is generated from api/openapi.json (OpenAPI 3.1.0, API version 1.0.0). Read the foundation guide for session handling, permissions, and examples.

Download the OpenAPI specification. The running service also publishes it at /api/openapi.json. API paths below are relative to your SongCollect service origin.

Versioned, language-independent SongCollect interface. Browser sessions use an HttpOnly cookie. Every mutation requires the configured APP_ORIGIN header; native clients must retain the cookie and send that origin too. Native token authentication and cross-origin browser hosting are future work. Repeated Idempotency-Key requests replay the committed response; PUT requires the quoted revision ETag in If-Match. Public routes expose active song heads only.

AuthenticationπŸ”—

  • developmentSession: apiKey, sent in cookie as songcollect.
  • session: apiKey, sent in cookie as __Host-songcollect.

Security alternatives listed on an endpoint mean either cookie is accepted. Endpoints marked public do not require a session.

EndpointsπŸ”—

GET /api/health/liveπŸ”—

Operation: live.

Authentication: public.

Responses

StatusDescriptionBodyHeaders
200application/json: Health
413Request body exceeds 32 KiBapplication/json: ErrorBody
429Rate limit exceededapplication/json: ErrorBody
500Unexpected server errorapplication/json: ErrorBody

GET /api/health/readyπŸ”—

Operation: ready.

Authentication: public.

Responses

StatusDescriptionBodyHeaders
200application/json: Health
413Request body exceeds 32 KiBapplication/json: ErrorBody
429Rate limit exceededapplication/json: ErrorBody
500Unexpected server errorapplication/json: ErrorBody
503application/json: Health

GET /api/v1/churchesπŸ”—

Operation: churches.

Authentication: session or developmentSession.

Responses

StatusDescriptionBodyHeaders
200application/json: Churches
401application/json: ErrorBody
413Request body exceeds 32 KiBapplication/json: ErrorBody
429Rate limit exceededapplication/json: ErrorBody
500Unexpected server errorapplication/json: ErrorBody

GET /api/v1/churches/{churchId}/songsπŸ”—

Operation: list.

Authentication: session or developmentSession.

Parameters

NameLocationRequiredTypeConstraints / description
churchIdpathYesstring (uuid)
qqueryNostringmaxLength: 200
offsetqueryNointeger (int64)minimum: 0; maximum: 100000

Responses

StatusDescriptionBodyHeaders
200application/json: Catalogue
400application/json: ErrorBody
401application/json: ErrorBody
404application/json: ErrorBody
413Request body exceeds 32 KiBapplication/json: ErrorBody
429Rate limit exceededapplication/json: ErrorBody
500Unexpected server errorapplication/json: ErrorBody

POST /api/v1/churches/{churchId}/songsπŸ”—

Operation: create.

Authentication: session or developmentSession.

Parameters

NameLocationRequiredTypeConstraints / description
churchIdpathYesstring (uuid)
OriginheaderYesstring
Idempotency-KeyheaderYesstring (uuid)

Request body (required)

Responses

StatusDescriptionBodyHeaders
201application/json: SongResponseETag: string; Location: string
400application/json: ErrorBody
401application/json: ErrorBody
403application/json: ErrorBody
404application/json: ErrorBody
409application/json: ErrorBody
413Request body exceeds 32 KiBapplication/json: ErrorBody
429Rate limit exceededapplication/json: ErrorBody
500Unexpected server errorapplication/json: ErrorBody

GET /api/v1/churches/{churchId}/songs/{songId}πŸ”—

Operation: get.

Authentication: session or developmentSession.

Parameters

NameLocationRequiredTypeConstraints / description
churchIdpathYesstring (uuid)
songIdpathYesstring (uuid)

Responses

StatusDescriptionBodyHeaders
200application/json: SongResponseETag: string β€” Quoted current revision
400application/json: ErrorBody
401application/json: ErrorBody
404application/json: ErrorBody
413Request body exceeds 32 KiBapplication/json: ErrorBody
429Rate limit exceededapplication/json: ErrorBody
500Unexpected server errorapplication/json: ErrorBody

PUT /api/v1/churches/{churchId}/songs/{songId}πŸ”—

Operation: update.

Authentication: session or developmentSession.

Parameters

NameLocationRequiredTypeConstraints / description
churchIdpathYesstring (uuid)
songIdpathYesstring (uuid)
OriginheaderYesstring
Idempotency-KeyheaderYesstring (uuid)
If-MatchheaderYesstringStrong ETag from the base revision, e.g. "1"

Request body (required)

Responses

StatusDescriptionBodyHeaders
200application/json: SongResponseETag: string
400application/json: ErrorBody
401application/json: ErrorBody
403application/json: ErrorBody
404application/json: ErrorBody
409application/json: ErrorBody
412application/json: ErrorBody
413Request body exceeds 32 KiBapplication/json: ErrorBody
428application/json: ErrorBody
429Rate limit exceededapplication/json: ErrorBody
500Unexpected server errorapplication/json: ErrorBody

GET /api/v1/churches/{churchId}/songs/{songId}/revisionsπŸ”—

Operation: revisions.

Authentication: session or developmentSession.

Parameters

NameLocationRequiredTypeConstraints / description
churchIdpathYesstring (uuid)
songIdpathYesstring (uuid)

Responses

StatusDescriptionBodyHeaders
200application/json: Revisions
400application/json: ErrorBody
401application/json: ErrorBody
404application/json: ErrorBody
413Request body exceeds 32 KiBapplication/json: ErrorBody
429Rate limit exceededapplication/json: ErrorBody
500Unexpected server errorapplication/json: ErrorBody

GET /api/v1/public/churches/{churchId}/songsπŸ”—

Operation: public_list.

Authentication: public.

Parameters

NameLocationRequiredTypeConstraints / description
churchIdpathYesstring (uuid)
qqueryNostringmaxLength: 200
offsetqueryNointeger (int64)minimum: 0; maximum: 100000

Responses

StatusDescriptionBodyHeaders
200application/json: Catalogue
400application/json: ErrorBody
404application/json: ErrorBody
413Request body exceeds 32 KiBapplication/json: ErrorBody
429Rate limit exceededapplication/json: ErrorBody
500Unexpected server errorapplication/json: ErrorBody

GET /api/v1/public/churches/{churchId}/songs/{songId}πŸ”—

Operation: public_get.

Authentication: public.

Parameters

NameLocationRequiredTypeConstraints / description
churchIdpathYesstring (uuid)
songIdpathYesstring (uuid)

Responses

StatusDescriptionBodyHeaders
200application/json: SongResponseETag: string
400application/json: ErrorBody
404application/json: ErrorBody
413Request body exceeds 32 KiBapplication/json: ErrorBody
429Rate limit exceededapplication/json: ErrorBody
500Unexpected server errorapplication/json: ErrorBody

POST /api/v1/sessionπŸ”—

Operation: login.

Authentication: public.

Parameters

NameLocationRequiredTypeConstraints / description
OriginheaderYesstringConfigured APP_ORIGIN

Request body (required)

Responses

StatusDescriptionBodyHeaders
204Signed in; HttpOnly session cookie setNo body
400application/json: ErrorBody
401application/json: ErrorBody
403application/json: ErrorBody
413Request body exceeds 32 KiBapplication/json: ErrorBody
429application/json: ErrorBody
500Unexpected server errorapplication/json: ErrorBody

DELETE /api/v1/sessionπŸ”—

Operation: logout.

Authentication: public.

Parameters

NameLocationRequiredTypeConstraints / description
OriginheaderYesstring

Responses

StatusDescriptionBodyHeaders
204Session revoked and cookie clearedNo body
403application/json: ErrorBody
413Request body exceeds 32 KiBapplication/json: ErrorBody
429Rate limit exceededapplication/json: ErrorBody
500Unexpected server errorapplication/json: ErrorBody

SchemasπŸ”—

CatalogueπŸ”—

PropertyRequiredTypeConstraints / description
churchYesChurch
hasMoreYesboolean
songsYesarray of Song
JSON schema
{
  "type": "object",
  "required": [
    "church",
    "songs",
    "hasMore"
  ],
  "properties": {
    "church": {
      "$ref": "#/components/schemas/Church"
    },
    "hasMore": {
      "type": "boolean"
    },
    "songs": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/Song"
      }
    }
  }
}

ChurchπŸ”—

PropertyRequiredTypeConstraints / description
idYesstring (uuid)
nameYesstring
roleNoRole or null
timeZoneYesstring
JSON schema
{
  "type": "object",
  "required": [
    "id",
    "name",
    "timeZone"
  ],
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid"
    },
    "name": {
      "type": "string"
    },
    "role": {
      "oneOf": [
        {
          "$ref": "#/components/schemas/Role"
        },
        {
          "type": "null"
        }
      ]
    },
    "timeZone": {
      "type": "string"
    }
  }
}

ChurchesπŸ”—

PropertyRequiredTypeConstraints / description
churchesYesarray of Church
JSON schema
{
  "type": "object",
  "required": [
    "churches"
  ],
  "properties": {
    "churches": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/Church"
      }
    }
  }
}

CredentialsπŸ”—

PropertyRequiredTypeConstraints / description
emailYesstring (email)maxLength: 254
passwordYesstringminLength: 1; maxLength: 256

Unknown properties are rejected.

JSON schema
{
  "type": "object",
  "required": [
    "email",
    "password"
  ],
  "properties": {
    "email": {
      "type": "string",
      "format": "email",
      "maxLength": 254
    },
    "password": {
      "type": "string",
      "maxLength": 256,
      "minLength": 1
    }
  },
  "additionalProperties": false
}

ErrorBodyπŸ”—

PropertyRequiredTypeConstraints / description
currentNoSong or null
errorYesstring
JSON schema
{
  "type": "object",
  "required": [
    "error"
  ],
  "properties": {
    "current": {
      "oneOf": [
        {
          "$ref": "#/components/schemas/Song"
        },
        {
          "type": "null"
        }
      ]
    },
    "error": {
      "type": "string"
    }
  }
}

HealthπŸ”—

PropertyRequiredTypeConstraints / description
statusYesstring
JSON schema
{
  "type": "object",
  "required": [
    "status"
  ],
  "properties": {
    "status": {
      "type": "string"
    }
  }
}

MetadataπŸ”—

PropertyRequiredTypeConstraints / description
alternateTitlesYesarray of stringmaxItems: 20
authorsYesarray of stringmaxItems: 30
copyrightYesstringmaxLength: 1000
songbooksYesarray of SongbookmaxItems: 30
themesYesarray of stringmaxItems: 30
titleYesstringminLength: 1; maxLength: 200

Unknown properties are rejected.

JSON schema
{
  "type": "object",
  "required": [
    "title",
    "alternateTitles",
    "authors",
    "copyright",
    "themes",
    "songbooks"
  ],
  "properties": {
    "alternateTitles": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "maxItems": 20
    },
    "authors": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "maxItems": 30
    },
    "copyright": {
      "type": "string",
      "maxLength": 1000
    },
    "songbooks": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/Songbook"
      },
      "maxItems": 30
    },
    "themes": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "maxItems": 30
    },
    "title": {
      "type": "string",
      "maxLength": 200,
      "minLength": 1
    }
  },
  "additionalProperties": false
}

MetadataInputπŸ”—

PropertyRequiredTypeConstraints / description
alternateTitlesNoarray of stringmaxItems: 20
authorsNoarray of stringmaxItems: 30
copyrightNostringmaxLength: 1000
songbooksNoarray of SongbookmaxItems: 30
themesNoarray of stringmaxItems: 30
titleYesstringminLength: 1; maxLength: 200

Unknown properties are rejected.

JSON schema
{
  "type": "object",
  "required": [
    "title"
  ],
  "properties": {
    "alternateTitles": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "maxItems": 20
    },
    "authors": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "maxItems": 30
    },
    "copyright": {
      "type": "string",
      "maxLength": 1000
    },
    "songbooks": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/Songbook"
      },
      "maxItems": 30
    },
    "themes": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "maxItems": 30
    },
    "title": {
      "type": "string",
      "maxLength": 200,
      "minLength": 1
    }
  },
  "additionalProperties": false
}

RevisionπŸ”—

PropertyRequiredTypeConstraints / description
createdAtYesstring (date-time)
idYesstring (uuid)
metadataYesMetadata
versionYesinteger (int32)
JSON schema
{
  "type": "object",
  "required": [
    "id",
    "version",
    "metadata",
    "createdAt"
  ],
  "properties": {
    "createdAt": {
      "type": "string",
      "format": "date-time"
    },
    "id": {
      "type": "string",
      "format": "uuid"
    },
    "metadata": {
      "$ref": "#/components/schemas/Metadata"
    },
    "version": {
      "type": "integer",
      "format": "int32"
    }
  }
}

RevisionsπŸ”—

PropertyRequiredTypeConstraints / description
revisionsYesarray of Revision
JSON schema
{
  "type": "object",
  "required": [
    "revisions"
  ],
  "properties": {
    "revisions": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/Revision"
      }
    }
  }
}

RoleπŸ”—

Type: string. allowed: "Administrator", "Editor", "Viewer"

JSON schema
{
  "type": "string",
  "enum": [
    "Administrator",
    "Editor",
    "Viewer"
  ]
}

SongπŸ”—

PropertyRequiredTypeConstraints / description
idYesstring (uuid)
metadataYesMetadata
revisionIdYesstring (uuid)
updatedAtYesstring (date-time)
versionYesinteger (int32)
JSON schema
{
  "type": "object",
  "required": [
    "id",
    "version",
    "revisionId",
    "metadata",
    "updatedAt"
  ],
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid"
    },
    "metadata": {
      "$ref": "#/components/schemas/Metadata"
    },
    "revisionId": {
      "type": "string",
      "format": "uuid"
    },
    "updatedAt": {
      "type": "string",
      "format": "date-time"
    },
    "version": {
      "type": "integer",
      "format": "int32"
    }
  }
}

SongResponseπŸ”—

PropertyRequiredTypeConstraints / description
songYesSong
JSON schema
{
  "type": "object",
  "required": [
    "song"
  ],
  "properties": {
    "song": {
      "$ref": "#/components/schemas/Song"
    }
  }
}

SongbookπŸ”—

PropertyRequiredTypeConstraints / description
bookYesstringminLength: 1; maxLength: 200
numberYesstringminLength: 1; maxLength: 30

Unknown properties are rejected.

JSON schema
{
  "type": "object",
  "required": [
    "book",
    "number"
  ],
  "properties": {
    "book": {
      "type": "string",
      "maxLength": 200,
      "minLength": 1
    },
    "number": {
      "type": "string",
      "maxLength": 30,
      "minLength": 1
    }
  },
  "additionalProperties": false
}

Search documentation

Type to search the documentation.