pages(),
blogPosts(), faqItems(), fetchskiMedia() and so on. A call is one line.
Arguments
One object per call
Path, query and body fields side by side:
listBlogs({ page: 2, perPage: 20 }). Leave it out when
nothing is required.A body is fields too
updateTestimonial({ id, quote: 'Great service' }) sends {"quote":"Great service"}.null is not sent
null or undefined leaves a field out, so a PATCH changes only what you name.Dates and files
A date takes a
Date or a string; a file a File named with its extension.Models
Every answer is a typed model, decoded for you.What each type becomes
What each type becomes
A field the site always sends is never optional. Date-times and Unix times are
Dates. Lists are
readonly arrays; maps readonly records. A field the site may send as null is typed | null.Enums stay open
Enums stay open
An enum is its known values or any string a newer site adds:
'draft' | 'published' | (string & {}).
Compare against its constant, AposMode.Draft.Answered, not required to write
Answered, not required to write
Some models are both an answer and a body. A field the site always sends (a testimonial’s
slug,
visibility, archived) is required when it answers, yet stays optional when you write:
updateTestimonial({ id, quote: '…' }) leaves the others alone.Every answer is checked
Every answer is checked
Against its type, before your code sees it. A value of the wrong type rejects with a
SiteRequestFailed naming the field, never coerced.Whole lists, missing documents, jobs
…All()fetches a page at a time as you iterate: see Paging.find…()sits beside eachget…(): only a 404 becomesnull.- A job’s
wait()needs the job route, which only the management key reaches: on an API key it throwsSiteConfigurationError.
What an API key reaches
- Content
- Feature routes
- Drafts and publishing
- Never
Every content type, with that type’s scopes:
content:<type>:read lists and reads the published
documents, :write creates and changes drafts (and reads them), :publish takes them live, and
:delete deletes. Pages, the media libraries and Site settings (global:*) included. Each
method’s reference page names its scope under Access; Required scopes lists them
all.Ids
A document’s id names its locale and mode:<document id>:<locale>:<mode>.
A create answers the id of its mode
Published by default (
…:en:published); aposMode: 'draft' makes only a draft (…:en:draft).Reads take either id
Or the bare document id.
Deleting takes the draft id
It removes both copies. The draft id is the published id with the last part changed.
Uploads
Upload aFile named with its extension: the site reads a file’s type from its name.
Blob, or a name without an extension, is refused before it leaves (RequestNotSent).
uploadAttachment() needs the write scope of a media type (content:images:write,
content:files:write or content:videos:write).A signed upload signs its SHA-256. A multipart body isn’t signed byte for byte: the request declares the
hex SHA-256 of the exact body in
X-Fetchski-Content-SHA256 and signs that digest in the body’s place. The
site checks the signature before it reads the upload, then the bytes against the digest, and stores nothing
that doesn’t match. The SDKs do this for you; Signing requests shows it by hand.Timeouts
Slow routes set their own
Each FetchskiAI route, and the blog import with images, carries its own timeout: the site’s
600-second cap per AI call plus 15 seconds. You never pass one per call.
The larger one wins
The client’s timeout (15 seconds by default) covers every other route. Raise it, and every call gets
at least that long.
A route without a method
Every route the site documents has a method, butrequest() calls any route exactly as the methods
do: the key, its signature, retries, the timeout and the same errors.
Next: errors
One class per failure, and what the SDK retries for you.