Rootless

Automate iOS, iPadOS, and macOS using plain JavaScript. Build custom widgets and interact directly with native APIs.

Download on the App Store
Rootless app interface

Plain JavaScript

Supports ES6. Scripts are stored as plain .js files on your disk.

Native APIs & Documentation

Integrate directly with iOS native APIs. Fully documented, available offline.

Siri Shortcuts

Trigger scripts via Siri. Present tables, websites, and custom HTML natively.

System Integration

Run from the Share Sheet, process inputs, and manage local files via Files.app.

x-callback-url

Communicate seamlessly and trigger workflows with other apps on your device.

Customizable & Ready

Tailor the code editor to your liking. Includes several example scripts to start immediately.

Documentation

Also inside the app, or as rootless.json.

Http

HTTP requests with caching

Performs a request and blocks until it answers. Every method takes the same options object. cache is honoured on GET only and falls back to a stale copy when the network fails; multipart sends a form-data body, which is the only way to upload a file.

Methods

Http.get(url, options?)HttpResponse ›

Perform an HTTP GET request.

  • url String required

    The URL to request.

  • options Any
    • headers Any

      Request headers as { name: value }.

    • timeout Duration

      How long to wait. Also accepts a plain number of seconds.

    • cache Duration

      Cache the response for this long and reuse it. GET only. A cached copy is also used when the network fails, however stale.

Http.post(url, options?)HttpResponse ›

Perform an HTTP POST request.

  • url String required

    The URL to request.

  • options Any
    • headers Any

      Request headers as { name: value }.

    • timeout Duration

      How long to wait. Also accepts a plain number of seconds.

    • body Any

      The request body. An object is sent as JSON; a string is sent as-is.

    • multipart Any

      A form-data body as { field: value }. The only way to upload a file.

Http.put(url, options?)HttpResponse ›

Perform an HTTP PUT request.

  • url String required

    The URL to request.

  • options Any
    • headers Any

      Request headers as { name: value }.

    • timeout Duration

      How long to wait. Also accepts a plain number of seconds.

    • body Any

      The request body. An object is sent as JSON; a string is sent as-is.

    • multipart Any

      A form-data body as { field: value }. The only way to upload a file.

Http.patch(url, options?)HttpResponse ›

Perform an HTTP PATCH request.

  • url String required

    The URL to request.

  • options Any
    • headers Any

      Request headers as { name: value }.

    • timeout Duration

      How long to wait. Also accepts a plain number of seconds.

    • body Any

      The request body. An object is sent as JSON; a string is sent as-is.

    • multipart Any

      A form-data body as { field: value }. The only way to upload a file.

Http.delete(url, options?)HttpResponse ›

Perform an HTTP DELETE request.

  • url String required

    The URL to request.

  • options Any
    • headers Any

      Request headers as { name: value }.

    • timeout Duration

      How long to wait. Also accepts a plain number of seconds.

    • body Any

      The request body. An object is sent as JSON; a string is sent as-is.

    • multipart Any

      A form-data body as { field: value }. The only way to upload a file.

Http.head(url, options?)HttpResponse ›

Perform an HTTP HEAD request.

  • url String required

    The URL to request.

  • options Any
    • headers Any

      Request headers as { name: value }.

    • timeout Duration

      How long to wait. Also accepts a plain number of seconds.

Http.request(url, options?)HttpResponse ›

Perform a generic HTTP request. Set method via options.method.

  • url String required

    The URL to request.

  • options Any
    • headers Any

      Request headers as { name: value }.

    • timeout Duration

      How long to wait. Also accepts a plain number of seconds.

    • body Any

      The request body. An object is sent as JSON; a string is sent as-is.

    • multipart Any

      A form-data body as { field: value }. The only way to upload a file.

    • cache Duration

      Cache the response for this long and reuse it. GET only. A cached copy is also used when the network fails, however stale.

    • method String

      "GET", "POST", "PUT", "PATCH", "DELETE" or "HEAD". Default "GET".

Http.getAll(urls, options?)[HttpResponse] ›

Fetch several URLs at once and get the responses in the same order. Serial requests add up and a widget's time budget is short.

  • urls [String] required

    The URLs to fetch.

  • options Any
    • headers Any

      Request headers as { name: value }.

    • timeout Duration

      How long to wait. Also accepts a plain number of seconds.

    • cache Duration

      Cache the response for this long and reuse it. GET only. A cached copy is also used when the network fails, however stale.

returns One response per URL, in the order given.

Examples

GET with caching

const res = Http.get("https://api.example.com/data", {
  cache: Duration.minutes(15),
  headers: { "Authorization": "Bearer token" }
});
if (res.ok) {
  const data = res.json;
}

POST request

const res = Http.post("https://api.example.com/submit", {
  body: { name: "test", value: 42 },
  timeout: Duration.seconds(10)
});
console.log(res.status); // 200

PUT / PATCH / DELETE

Http.put("https://api.example.com/items/1", {
  body: { name: "updated" }
});
Http.patch("https://api.example.com/items/1", {
  body: { status: "active" }
});
Http.delete("https://api.example.com/items/1");

Response properties

// res.ok. True if status 200-299
// res.status. HTTP status code
// res.text. Body as string
// res.json. Parsed JSON or null
// res.headers. Response headers (lowercase keys)
// res.url. Final URL (after redirects)
// res.mimeType. Response MIME type
// res.error, "timeout" | "network_error" | ...
// res.stale. True if from stale cache

Reading response headers

const res = Http.get("https://api.example.com/data");
const contentType = res.headers["content-type"];
const rateLimit = res.headers["x-ratelimit-remaining"];

Uploading a file

Http.post(url, { multipart: [
  { name: "caption", value: "Today's chart" },
  { name: "file", base64: chart, filename: "chart.png", contentType: "image/png" },
]});