Ramadan Last 10 Nights Campaign

Used by thousands of students worldwide - help us reach 150 members

... / 150 members...
APIFiles & Videos

Files & Videos

/files

Library of uploaded documents and videos stored in S3, with metadata (title, author, tags, categories, visibility) kept in MongoDB. Files and videos share the same underlying File model. Authentication failures are answered by the auth middleware with plain-text bodies (401 no token, 403 invalid token or missing role, 404 when the token's user no longer exists).

POST/files/upload

Upload a file

Auth required

Uploads a single file to S3 under a unique `uploads/<uuid>-<originalname>` key and saves its metadata. Any file type is accepted. `visibility` falls back to the model default `private` when omitted; any value other than `public`/`private` fails validation with a 500. The response contains the full stored document, including `s3Key` and `s3Bucket`.

Send the body as multipart/form-data.

Body parameters

filerequired
file
The file to upload, under the field name `file`. Exactly one file, any MIME type, max 1 GB.
title
string
Display name, stored as `fileName`.Default: original file name
author
string
Author of the document.Default: 'Unknown'
tags
string
Comma-separated list of tags; each entry is trimmed.Default: []
categories
string
Comma-separated list of categories; each entry is trimmed.Default: ['uncategorized']
visibility
string
`'public'` or `'private'`.Default: 'private'

Errors

  • 400No file uploaded. Only returned when `title` is supplied; without both a file and a `title` the handler fails earlier and answers 500.
  • 401No bearer token provided (plain-text body)
  • 403Invalid or expired token, or the user lacks the required role (plain-text body)
  • 500S3/database/validation error (e.g. invalid `visibility`). A file over 1 GB or an unexpected file field is answered with a plain-text 500 by the global error handler.
Request
curl -X POST "https://app.ummahspot.com/files/upload" \
  -H "Authorization: Bearer $SHARH_TOKEN" \
  -F "file=@/path/to/file"
Response · 201
{
  "message": "File uploaded and metadata saved successfully",
  "file": {
    "_id": "66f2d1e2f3a4b5c6d7e8f901",
    "fileName": "Ajrumiyyah Notes",
    "s3Key": "uploads/3c1f9a52-7a0b-4d0e-9d55-0a4f1b2c3d4e-ajrumiyyah-notes.pdf",
    "author": "Ibn Ajurrum",
    "s3Bucket": "sharh-files",
    "fileSize": 1843200,
    "fileType": "application/pdf",
    "tags": ["nahw", "grammar"],
    "categories": ["arabic"],
    "visibility": "public",
    "thumbnailKey": null,
    "uploadDate": "2026-09-18T09:00:00.000Z",
    "createdDate": "2026-09-18T09:00:00.000Z",
    "updatedDate": "2026-09-18T09:00:00.000Z",
    "__v": 0
  }
}
GET/files/download/:id

Download a file

Auth required

Streams the file contents from S3 through the API. Access depends on the file's `visibility`: public files are available to any signed-in user; private files only to admins, to the user who owns the OCR book created from that file, and to editors when the file is the source file of an OCR book. Anyone else gets the same 404 as for a missing file. No `Content-Disposition` header is set, so browsers render the file inline when they can.

Path parameters

id
string
File ObjectId

Errors

  • 401No bearer token provided (plain-text body)
  • 403Invalid or expired token, or the user lacks the required role (plain-text body)
  • 404File not found, or the file is private and the caller may not access it (`{"message":"File not found"}` in both cases)
  • 500Error retrieving the file (including a malformed `id`)
Request
curl -X GET "https://app.ummahspot.com/files/download/:id" \
  -H "Authorization: Bearer $SHARH_TOKEN"
Response · 200
Binary stream of the file. Content-Type is the stored fileType (falls back to application/octet-stream).
GET/files/view/:id

Get a temporary view URL for a file

Auth required

Returns a presigned S3 URL for the file, valid for 5 minutes. Access depends on the file's `visibility`: public files are available to any signed-in user; private files only to admins, to the user who owns the OCR book created from that file, and to editors when the file is the source file of an OCR book. Anyone else gets the same 404 as for a missing file.

Path parameters

id
string
File ObjectId

Errors

  • 401No bearer token provided (plain-text body)
  • 403Invalid or expired token, or the user lacks the required role (plain-text body)
  • 404File not found, or the file is private and the caller may not access it (`{"message":"File not found"}` in both cases)
  • 500Error generating the view link (including a malformed `id`)
Request
curl -X GET "https://app.ummahspot.com/files/view/:id" \
  -H "Authorization: Bearer $SHARH_TOKEN"
Response · 200
{
  "url": "https://sharh-files.s3.amazonaws.com/uploads/3c1f9a52-...-ajrumiyyah-notes.pdf?X-Amz-Expires=300&X-Amz-Signature=..."
}
GET/files/:id/metadata

Get file metadata

Auth required

Returns a subset of the stored metadata for one file. Access depends on the file's `visibility`: public files are available to any signed-in user; private files only to admins, to the user who owns the OCR book created from that file, and to editors when the file is the source file of an OCR book. Anyone else gets the same 404 as for a missing file.

Path parameters

id
string
File ObjectId

Errors

  • 401No bearer token provided (plain-text body)
  • 403Invalid or expired token, or the user lacks the required role (plain-text body)
  • 404File not found, or the file is private and the caller may not access it (`{"message":"File not found"}` in both cases)
  • 500Database error (including a malformed `id`)
Request
curl -X GET "https://app.ummahspot.com/files/:id/metadata" \
  -H "Authorization: Bearer $SHARH_TOKEN"
Response · 200
{
  "fileName": "Ajrumiyyah Notes",
  "fileType": "application/pdf",
  "author": "Ibn Ajurrum",
  "uploadDate": "2026-09-18T09:00:00.000Z",
  "tags": ["nahw", "grammar"],
  "categories": ["arabic"]
}
GET/files

List and search files

Public

Lists file records (uploaded videos are stored in the same collection and are included). No authentication is required and results are limited to `visibility: public`; the handler reads an optional bearer token itself and only an admin token lifts that restriction. There is no pagination — every match is returned. `s3Key` and `s3Bucket` are never included. With `searchTerm`, a MongoDB full-text search over fileName, author, tags and categories is used, results are sorted by relevance and each item carries a `score`; otherwise no sort order is applied. All filters are combined with AND.

Query parameters

fileName
string
Case-insensitive regex match on the file name.
author
string
Case-insensitive regex match on the author.
uploadDate
string
Exact match on the upload timestamp (parsed with `new Date()`).
fileSize
number
Exact file size in bytes.
fileType
string
Case-insensitive regex match on the MIME type, e.g. `pdf`.
tags
string
Comma-separated tags; matches files having at least one of them (case-insensitive, partial match).
categories
string
Comma-separated categories; matches files having at least one of them (case-insensitive, partial match).
searchTerm
string
Full-text search term; enables relevance sorting and adds `score` to each result.

Errors

  • 500Database error (e.g. an invalid regex in a filter)
Request
curl -X GET "https://app.ummahspot.com/files"
Response · 200
{
  "files": [
    {
      "_id": "66f2d1e2f3a4b5c6d7e8f901",
      "fileName": "Ajrumiyyah Notes",
      "author": "Ibn Ajurrum",
      "fileSize": 1843200,
      "fileType": "application/pdf",
      "tags": ["nahw", "grammar"],
      "categories": ["arabic"],
      "visibility": "public",
      "thumbnailKey": null,
      "uploadDate": "2026-09-18T09:00:00.000Z",
      "createdDate": "2026-09-18T09:00:00.000Z",
      "updatedDate": "2026-09-18T09:00:00.000Z",
      "__v": 0
    }
  ]
}
POST/files/videos/upload

Upload a video

Auth required

Uploads a single video to S3 under `videos/<uuid>-<originalname>`, generates a 320x180 JPEG thumbnail from the 2-second mark with ffmpeg, uploads it under `thumbnails/`, and saves the metadata. If thumbnail generation fails the upload still succeeds, but the record keeps the intended `thumbnailKey` and the returned `thumbnailUrl` will point at a missing object. `thumbnailUrl` is a presigned URL valid for 1 hour.

Send the body as multipart/form-data.

Body parameters

videorequired
file
The video, under the field name `video`. Exactly one file, max 1 GB. Allowed MIME types: video/mp4, video/quicktime, video/x-msvideo, video/x-ms-wmv, video/webm.
fileName
string
Display name of the video.Default: original file name
description
string
Video description.Default: ''
author
string
Author / presenter.Default: 'Unknown'
tags
string
Comma-separated list of tags; each entry is trimmed.Default: []
categories
string
Comma-separated list of categories; each entry is trimmed.Default: []
visibility
string
`'public'` or `'private'`.Default: 'private'

Errors

  • 400No video uploaded
  • 401No bearer token provided (plain-text body)
  • 403Invalid or expired token, or the user lacks the required role (plain-text body)
  • 500S3/database/validation error (e.g. invalid `visibility`). A disallowed MIME type or a file over 1 GB is answered with a plain-text 500 by the global error handler.
Request
curl -X POST "https://app.ummahspot.com/files/videos/upload" \
  -H "Authorization: Bearer $SHARH_TOKEN" \
  -F "video=@/path/to/file"
Response · 201
{
  "message": "Video uploaded successfully",
  "video": {
    "id": "66f2e4a5b6c7d8e9f0a1b2c3",
    "fileName": "Getting started with the reader",
    "author": "Sharh Team",
    "description": "A five minute tour of the book reader.",
    "thumbnailUrl": "https://sharh-files.s3.amazonaws.com/thumbnails/9e8d7c6b-...-tour.jpg?X-Amz-Signature=..."
  }
}
GET/files/videos

List videos

Public

Paginated list of records from the shared file collection, newest upload first. Note that the handler does not filter by MIME type, so non-video files uploaded through `/files/upload` also appear. No authentication is required and results are limited to `visibility: public`; the handler reads an optional bearer token itself and only an admin token lifts that restriction. `s3Key` and `s3Bucket` are never included. Records with a `thumbnailKey` get a 1-hour presigned `thumbnailUrl` (null if URL generation fails). Page-based pagination via `page` and `limit`.

Query parameters

fileName
string
Case-insensitive regex match on the name.
author
string
Case-insensitive regex match on the author.
tags
string
Comma-separated tags; matches records having at least one of them (case-insensitive, partial match).
categories
string
Comma-separated categories; matches records having at least one of them (case-insensitive, partial match).
page
number
1-based page number.Default: 1
limit
number
Items per page.Default: 10

Errors

  • 500Database error (e.g. an invalid regex in a filter)
Request
curl -X GET "https://app.ummahspot.com/files/videos"
Response · 200
{
  "videos": [
    {
      "_id": "66f2e4a5b6c7d8e9f0a1b2c3",
      "fileName": "Getting started with the reader",
      "author": "Sharh Team",
      "fileSize": 52428800,
      "fileType": "video/mp4",
      "description": "A five minute tour of the book reader.",
      "tags": ["tutorial"],
      "categories": ["getting-started"],
      "visibility": "public",
      "thumbnailKey": "thumbnails/9e8d7c6b-5a4f-4e3d-2c1b-0a9f8e7d6c5b-tour.jpg",
      "uploadDate": "2026-09-18T09:30:00.000Z",
      "createdDate": "2026-09-18T09:30:00.000Z",
      "updatedDate": "2026-09-18T09:30:00.000Z",
      "__v": 0,
      "thumbnailUrl": "https://sharh-files.s3.amazonaws.com/thumbnails/9e8d7c6b-...-tour.jpg?X-Amz-Signature=..."
    }
  ],
  "currentPage": 1,
  "totalPages": 1,
  "totalVideos": 1
}
GET/files/videos/:id

Get video details and playback URL

Auth required

Returns the video's metadata with a presigned playback URL (`viewUrl`) and thumbnail URL, both valid for 1 hour. Unlike the list endpoint, this route requires a logged-in user. Visibility is enforced: private videos are only returned to admins; everyone else gets a 403. `thumbnailUrl` is null when the record has no thumbnail.

Path parameters

id
string
Video (File) ObjectId

Errors

  • 401No bearer token provided (plain-text body)
  • 403Invalid or expired token, or the user lacks the required role (plain-text body)
  • 403The video is private and the current user is not an admin (JSON body)
  • 404Video not found
  • 500Database/S3 error (including a malformed `id`)
Request
curl -X GET "https://app.ummahspot.com/files/videos/:id" \
  -H "Authorization: Bearer $SHARH_TOKEN"
Response · 200
{
  "id": "66f2e4a5b6c7d8e9f0a1b2c3",
  "fileName": "Getting started with the reader",
  "description": "A five minute tour of the book reader.",
  "author": "Sharh Team",
  "uploadDate": "2026-09-18T09:30:00.000Z",
  "createdDate": "2026-09-18T09:30:00.000Z",
  "updatedDate": "2026-09-18T09:30:00.000Z",
  "fileType": "video/mp4",
  "fileSize": 52428800,
  "tags": ["tutorial"],
  "categories": ["getting-started"],
  "visibility": "public",
  "viewUrl": "https://sharh-files.s3.amazonaws.com/videos/1a2b3c4d-...-tour.mp4?X-Amz-Signature=...",
  "thumbnailUrl": "https://sharh-files.s3.amazonaws.com/thumbnails/9e8d7c6b-...-tour.jpg?X-Amz-Signature=..."
}