GraceSoft Storehouse

API reference · v1.0.1

GraceSoft Storehouse API

Public-domain Proverbs and original GraceSoft quips, as static JSON.

Base URL https://api.gracesoft.dev

GraceSoft Storehouse is a read-only, versioned REST API. Every response is a static JSON file served from Vercel's global CDN, so it's fast, cacheable, and needs no API key.

Envelope. Successful responses are { "data": …, "meta": { "version", "generatedAt" } }. Lists also carry meta.count. Errors are { "error": { "status", "code", "message" }, "meta" }.

Time zone. "Today" is always evaluated in Asia/Singapore (UTC+8). New quips go live at 00:00 SGT on their publishAt date, after the daily scheduled rebuild.

Caching. Responses carry ETag and Cache-Control headers; send If-None-Match to get 304 Not Modified.

CORS. Browser access is limited to an allowlist of GraceSoft origins. Server-side clients (bots, scripts) can call the API from anywhere.

Versioning. Additive changes stay in v1. Breaking changes go to v2.

Licence. Proverbs text is public domain. Quips are © D.L. (GraceSoft) — see CONTENT_LICENSE.md for terms of reuse.

Translations

The public-domain Bible translations available.

GET /v1/translations.json

List translations

Every translation in the registry, sorted by code.

Responses

  • 200 The translation registry. — TranslationListResponse
  • 304 The resource hasn't changed since the If-None-Match ETag.
  • 4XX The request can't be served, e.g. 405 for any method other than GET, HEAD, or OPTIONS. — ErrorResponse

Example

curl https://api.gracesoft.dev/v1/translations.json
{
  "data": [
    {
      "code": "asv",
      "name": "American Standard Version",
      "year": 1901,
      "language": "en",
      "license": "Public Domain",
      "source": "https://ebible.org/find/details.php?id=eng-asv"
    },
    {
      "code": "kjv",
      "name": "King James Version",
      "year": 1769,
      "language": "en",
      "license": "Public Domain",
      "source": "https://ebible.org/find/details.php?id=eng-kjv2006"
    },
    {
      "code": "web",
      "name": "World English Bible",
      "year": 2000,
      "language": "en",
      "license": "Public Domain",
      "source": "https://ebible.org/find/details.php?id=engwebp"
    }
  ],
  "meta": {
    "version": "1.0.1",
    "generatedAt": "2026-10-19T10:30:38.042Z",
    "count": 3
  }
}

Proverbs

The 31 chapters of the book of Proverbs, per translation.

GET /v1/proverbs/{code}/index.json

List chapters

The 31 chapters of Proverbs for one translation, with verse counts.

Parameters

NameInTypeDescription
code requiredpathstring

A translation code from /v1/translations.json, e.g. kjv.

Responses

  • 200 Chapter summaries for one translation. — ChapterListResponse
  • 304 The resource hasn't changed since the If-None-Match ETag.
  • 404 No resource exists at this path. — ErrorResponse

Example

curl https://api.gracesoft.dev/v1/proverbs/kjv/index.json
{
  "data": [
    {
      "translation": "kjv",
      "chapter": 1,
      "verseCount": 33,
      "href": "/v1/proverbs/kjv/1.json"
    },
    {
      "translation": "kjv",
      "chapter": 2,
      "verseCount": 22,
      "href": "/v1/proverbs/kjv/2.json"
    },
    {
      "translation": "kjv",
      "chapter": 3,
      "verseCount": 35,
      "href": "/v1/proverbs/kjv/3.json"
    },
    "… 28 more"
  ],
  "meta": {
    "version": "1.0.1",
    "generatedAt": "2026-10-19T10:30:38.042Z",
    "count": 31
  }
}
GET /v1/proverbs/{code}/{chapter}.json

Get a chapter

One chapter of Proverbs, with every verse.

Parameters

NameInTypeDescription
code requiredpathstring

A translation code from /v1/translations.json, e.g. kjv.

chapter requiredpathinteger (1–31)

Chapter number, 1–31.

Responses

  • 200 One chapter with its verses. — ChapterResponse
  • 304 The resource hasn't changed since the If-None-Match ETag.
  • 404 No resource exists at this path. — ErrorResponse

Example

curl https://api.gracesoft.dev/v1/proverbs/kjv/3.json
{
  "data": {
    "translation": "kjv",
    "translationName": "King James Version",
    "chapter": 3,
    "verses": [
      {
        "verse": 1,
        "text": "My son, forget not my law; but let thine heart keep my commandments:"
      },
      {
        "verse": 2,
        "text": "For length of days, and long life, and peace, shall they add to thee."
      },
      {
        "verse": 3,
        "text": "Let not mercy and truth forsake thee: bind them about thy neck; write them upon the table of thine heart:"
      },
      "… 32 more"
    ]
  },
  "meta": {
    "version": "1.0.1",
    "generatedAt": "2026-10-19T10:30:38.042Z"
  }
}
GET /v1/proverbs/{code}/today Dynamic

Get today's chapter

The chapter matching today's day of the month in Asia/Singapore ("a Proverb a day"). On the 19th, this is chapter 19.

Served by a Vercel Function that reads the static chapter file; responses are cached until the next 00:00 SGT. Rate-limited.

Parameters

NameInTypeDescription
code requiredpathstring

A translation code from /v1/translations.json, e.g. kjv.

Responses

  • 200 One chapter with its verses. — ChapterResponse
  • 404 No resource exists at this path. — ErrorResponse
  • 429 Rate limit exceeded (60 requests a minute per IP on the dynamic endpoints). Returned by the Vercel Firewall, so the body isn't the JSON error shape. Wait a minute and retry.

Example

curl https://api.gracesoft.dev/v1/proverbs/web/today
{
  "data": {
    "translation": "web",
    "translationName": "World English Bible",
    "chapter": 3,
    "verses": [
      {
        "verse": 1,
        "text": "My son, don’t forget my teaching, but let your heart keep my commandments,"
      },
      {
        "verse": 2,
        "text": "for they will add to you length of days, years of life, and peace."
      },
      {
        "verse": 3,
        "text": "Don’t let kindness and truth forsake you. Bind them around your neck. Write them on the tablet of your heart."
      },
      "… 32 more"
    ]
  },
  "meta": {
    "version": "1.0.1",
    "generatedAt": "2026-10-19T10:30:38.042Z"
  }
}

Quips

Original GraceSoft quips and puns. Only published quips are served.

GET /v1/quips/index.json

List quips

Every published quip, sorted by id. Drafts and future-dated quips are never included.

Responses

  • 200 Every published quip. — QuipListResponse
  • 304 The resource hasn't changed since the If-None-Match ETag.
  • 4XX The request can't be served, e.g. 405 for any method other than GET, HEAD, or OPTIONS. — ErrorResponse

Example

curl https://api.gracesoft.dev/v1/quips/index.json
{
  "data": [
    {
      "id": 1,
      "slug": "when-youre-on-a-keto-diet",
      "variant": "statement",
      "punchline": "When you're on a keto diet, you gotta lock down your intake.",
      "tags": [
        "food"
      ],
      "createdAt": "2026-10-06",
      "publishAt": "2026-10-06"
    },
    {
      "id": 2,
      "slug": "oh-oh-oats",
      "variant": "qa",
      "question": "What does Santa like to have for breakfast?",
      "punchline": "Oh, oh, oats.",
      "tags": [
        "food",
        "christmas"
      ],
      "createdAt": "2026-10-06",
      "publishAt": "2026-10-06"
    },
    {
      "id": 3,
      "slug": "young-tau-foo",
      "variant": "qa",
      "question": "What hawker dish would you consume for youthfulness?",
      "punchline": "Young tau foo.",
      "tags": [
        "food",
        "singapore",
        "hawker"
      ],
      "createdAt": "2026-10-06",
      "publishAt": "2026-10-06"
    },
    "… 62 more"
  ],
  "meta": {
    "version": "1.0.1",
    "generatedAt": "2026-10-19T10:30:38.042Z",
    "count": 65
  }
}
GET /v1/quips/{id}.json

Get a quip

One published quip. Unpublished, draft, and retired ids return 404.

Parameters

NameInTypeDescription
id requiredpathinteger (≥ 1)

The quip's permanent id.

Responses

  • 200 One published quip. — QuipResponse
  • 304 The resource hasn't changed since the If-None-Match ETag.
  • 404 No resource exists at this path. — ErrorResponse

Example

curl https://api.gracesoft.dev/v1/quips/2.json
{
  "data": {
    "id": 2,
    "slug": "oh-oh-oats",
    "variant": "qa",
    "question": "What does Santa like to have for breakfast?",
    "punchline": "Oh, oh, oats.",
    "tags": [
      "food",
      "christmas"
    ],
    "createdAt": "2026-10-06",
    "publishAt": "2026-10-06"
  },
  "meta": {
    "version": "1.0.1",
    "generatedAt": "2026-10-19T10:30:38.042Z"
  }
}
GET /v1/quips/random Dynamic

Get a random quip

A random published quip. Never cached. Served by a Vercel Function that reads /v1/quips/index.json. Rate-limited.

Parameters

NameInTypeDescription
tagquerystring

Only pick from quips with this tag.

Responses

  • 200 One published quip. — QuipResponse
  • 404 No resource exists at this path. — ErrorResponse
  • 429 Rate limit exceeded (60 requests a minute per IP on the dynamic endpoints). Returned by the Vercel Firewall, so the body isn't the JSON error shape. Wait a minute and retry.

Example

curl https://api.gracesoft.dev/v1/quips/random?tag=food
{
  "data": {
    "id": 2,
    "slug": "oh-oh-oats",
    "variant": "qa",
    "question": "What does Santa like to have for breakfast?",
    "punchline": "Oh, oh, oats.",
    "tags": [
      "food",
      "christmas"
    ],
    "createdAt": "2026-10-06",
    "publishAt": "2026-10-06"
  },
  "meta": {
    "version": "1.0.1",
    "generatedAt": "2026-10-19T10:30:38.042Z"
  }
}

Schemas

Meta

FieldTypeDescription
version requiredstring

API release version (semver).

generatedAt requiredstring (date-time)

When this response was built.

ListMeta

FieldTypeDescription
version requiredstring

API release version (semver).

generatedAt requiredstring (date-time)

When this response was built.

count requiredinteger (≥ 0)

Number of items in data.

Translation

FieldTypeDescription
code requiredstring

name requiredstring

year requiredinteger

language requiredstring

ISO 639-1 language code.

license required"Public Domain"

source requiredstring (uri)

Where the text was obtained.

ChapterSummary

FieldTypeDescription
translation requiredstring

chapter requiredinteger (1–31)

verseCount requiredinteger (≥ 1)

href requiredstring

Path to the chapter resource.

Verse

FieldTypeDescription
verse requiredinteger (≥ 1)

text requiredstring

Plain text (no Markdown or HTML). May contain curly quotes and em dashes.

Chapter

FieldTypeDescription
translation requiredstring

translationName requiredstring

chapter requiredinteger (1–31)

verses requiredVerse[]

Quip

FieldTypeDescription
id requiredinteger (≥ 1)

Permanent id; never reused.

slug requiredstring

variant required"qa" | "statement"

qa has a question and a punchline; statement has only a punchline.

questionstring

Present only when variant is qa.

punchline requiredstring

Plain text. Paragraphs are separated by a blank line (\n\n).

tags requiredstring[]

createdAt requiredstring

ISO 8601 date (YYYY-MM-DD) or date-time with offset.

publishAt requiredstring

ISO 8601 date or date-time. A date means 00:00 Asia/Singapore.

TranslationListResponse

FieldTypeDescription
data requiredTranslation[]

meta requiredListMeta

ChapterResponse

FieldTypeDescription
data requiredChapter

meta requiredMeta

QuipListResponse

FieldTypeDescription
data requiredQuip[]

meta requiredListMeta

QuipResponse

FieldTypeDescription
data requiredQuip

meta requiredMeta

ErrorResponse

FieldTypeDescription
error requiredobject

meta requiredMeta