Skip to content
Rigel docs
Open Rigel

Download a file's bytes

files.content

GET/api/v1/households/{household_id}/files/{file_id}/content

  • Route

Streams the display copy, or the original when there is none. copy picks one, and download=1 asks the browser to save it. Supports a single Range, ETag revalidation with If-None-Match, and HEAD. Only inline types (images, PDFs, video, audio) are served as themselves; anything else is application/octet-stream as an attachment. See the files guide.

Parameters#

Download a file's bytes: parameters
FieldDescription
household_idpathstringrequired

The household's ID.

file_idpathstringrequired

The file's ID, such as fil_01JC…

copyqueryone of: original, displayoptional

Which copy. Defaults to the display copy, else the original.

downloadqueryone of: 0, 1optional

1 to have the browser save the file instead of showing it.

Rangeheaderstringoptional

A single byte range: bytes=0-99, bytes=100- or bytes=-100.

If-None-Matchheaderstringoptional

An ETag from an earlier response.

Response#

200 The bytes.

The body is the raw bytes, as */*.

Errors#

Every error has the same envelope: error.code, error.message, error.details, error.recovery and error.request_id.

Download a file's bytes: errors
StatusCodeWhen
400validation_failedA field is missing, misspelled or out of range. details.fields lists each problem.
401unauthenticatedThe request has no valid session.
404not_foundThe household doesn't exist, or you aren't a member of it.
416Read error.codeDescribed above.

Examples#

These are real. Each was recorded from a sample household, the Okafors, running through the whole API when this site was built.

Download a file

Without copy, you get the display copy, or the original when there isn't one.

Request, curl
curl 'https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/files/fil_01M6V9CS96RRJQEBVXVCKMMR0T/content' \
  -H "Cookie: rigel_session=$RIGEL_SESSION"
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/files/fil_01M6V9CS96RRJQEBVXVCKMMR0T/content", {
  headers: {
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
});
const data = await response.json();
Request, HTTP
GET /api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/files/fil_01M6V9CS96RRJQEBVXVCKMMR0T/content HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Response, 200
HTTP/1.1 200 OK
Content-Type: image/png
Content-Length: 342
X-Request-Id: req_01M6V9CS9S7MMQHMTXRJPYPGXJ
ETag: "display-01M6V9CS9KGTGQ98QMTE123W11"
Content-Disposition: inline; filename="pantry-middle-shelf.png"; filename*=UTF-8''pantry-middle-shelf.png

(342 bytes of image/png; The file's bytes.)

Download the original

download=1 asks for an attachment, so a browser saves the file instead of showing it.

Request, curl
curl 'https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/files/fil_01M6V9CS96RRJQEBVXVCKMMR0T/content?copy=original&download=1' \
  -H "Cookie: rigel_session=$RIGEL_SESSION"
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/files/fil_01M6V9CS96RRJQEBVXVCKMMR0T/content?copy=original&download=1", {
  headers: {
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
});
const data = await response.json();
Request, HTTP
GET /api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/files/fil_01M6V9CS96RRJQEBVXVCKMMR0T/content?copy=original&download=1 HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Response, 200
HTTP/1.1 200 OK
Content-Type: image/png
Content-Length: 655
X-Request-Id: req_01M6V9CS9WJWH4MZ2BVDEWZMZX
ETag: "original-01M6V9CS9AY558G6KYPK0VRFC5"
Content-Disposition: attachment; filename="pantry-middle-shelf.png"; filename*=UTF-8''pantry-middle-shelf.png

(655 bytes of image/png; The file's bytes.)

Download part of a file

One byte range, as a video player asks for.

Request, curl
curl 'https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/files/fil_01M6V9CS96RRJQEBVXVCKMMR0T/content' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Range: bytes=0-99'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/files/fil_01M6V9CS96RRJQEBVXVCKMMR0T/content", {
  headers: {
    Range: "bytes=0-99",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
});
const data = await response.json();
Request, HTTP
GET /api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/files/fil_01M6V9CS96RRJQEBVXVCKMMR0T/content HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Range: bytes=0-99
Response, 206
HTTP/1.1 206
Content-Type: image/png
Content-Length: 100
X-Request-Id: req_01M6V9CS9X7WFVYWKF5KAD7H3G
ETag: "display-01M6V9CS9KGTGQ98QMTE123W11"
Content-Range: bytes 0-99/342
Content-Disposition: inline; filename="pantry-middle-shelf.png"; filename*=UTF-8''pantry-middle-shelf.png

(100 bytes of image/png; The file's bytes.)

Download a file that hasn't changed

Send the ETag you have as If-None-Match and the API answers 304 with no body.

Request, curl
curl 'https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/files/fil_01M6V9CS96RRJQEBVXVCKMMR0T/content' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'If-None-Match: "display-01M6V9CS9KGTGQ98QMTE123W11"'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/files/fil_01M6V9CS96RRJQEBVXVCKMMR0T/content", {
  headers: {
    "If-None-Match": "\"display-01M6V9CS9KGTGQ98QMTE123W11\"",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
});
const data = await response.json();
Request, HTTP
GET /api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/files/fil_01M6V9CS96RRJQEBVXVCKMMR0T/content HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
If-None-Match: "display-01M6V9CS9KGTGQ98QMTE123W11"
Response, 304
HTTP/1.1 304
X-Request-Id: req_01M6V9CS9YR96XCBJHBP4G4ZBC
ETag: "display-01M6V9CS9KGTGQ98QMTE123W11"
Content-Disposition: inline; filename="pantry-middle-shelf.png"; filename*=UTF-8''pantry-middle-shelf.png

A byte range past the end

Request, curl
curl 'https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/files/fil_01M6V9CS96RRJQEBVXVCKMMR0T/content' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Range: bytes=999999-'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/files/fil_01M6V9CS96RRJQEBVXVCKMMR0T/content", {
  headers: {
    Range: "bytes=999999-",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
});
const data = await response.json();
Request, HTTP
GET /api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/files/fil_01M6V9CS96RRJQEBVXVCKMMR0T/content HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Range: bytes=999999-
Response, 416
HTTP/1.1 416 Range Not Satisfiable
Content-Type: application/json
X-Request-Id: req_01M6V9CS9ZEN0HZTPY4AJ1WH42
Content-Range: bytes */342

{
  "error": {
    "code": "range_not_satisfiable",
    "message": "That byte range is outside the file.",
    "details": {
      "size": 342
    },
    "recovery": "Ask for a range within the file's size, or omit Range.",
    "request_id": "req_01M6V9CS9ZEN0HZTPY4AJ1WH42"
  }
}

Download a file that doesn't exist

Request, curl
curl 'https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/files/fil_01JC0000000000000000000000/content' \
  -H "Cookie: rigel_session=$RIGEL_SESSION"
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/files/fil_01JC0000000000000000000000/content", {
  headers: {
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
});
const data = await response.json();
Request, HTTP
GET /api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/files/fil_01JC0000000000000000000000/content HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Response, 404
HTTP/1.1 404 Not Found
Content-Type: application/json
X-Request-Id: req_01M6V9CTCZSCMKTM461EX0QE6Y

{
  "error": {
    "code": "not_found",
    "message": "That file wasn't found.",
    "details": {},
    "recovery": "Check the ID. You can only reach households you're a member of.",
    "request_id": "req_01M6V9CTCZSCMKTM461EX0QE6Y"
  }
}

Rigel is in early access, and sign-up is by invitation. Open Rigel