Configuration to retrieve the State Backed token to use for all requests.
Optional
opts: ClientOptsOptions for the client.
Readonly
billingOptional
signal: AbortSignalReadonly
identityAdministrative APIs to manage identity providers.
An identity provider is a configuration for validating and extracting claims from JWTs created by a third-party identity provider (e.g. Auth0, Supabase, etc.).
Those claims can then be used by token providers to generate State Backed tokens.
This token exchange allows fully-secure, end-to-end authorized requests directly from client code without needing any server and without having to change identity providers.
Delete an identity provider configuration
identity provider configuration. At least one of aud
and iss
must be provided.
Optional
aud?: stringAudience for the identity provider (at least one of aud or iss must be provided).
Optional
iss?: stringIssuer for the identity provider (at least one of aud or iss must be provided).
Optional
signal: AbortSignalan optional AbortSignal to abort the request
Retrieve a page of identity providers.
Optional
opts: ListOptionsoptions for the list operation
Optional
signal: AbortSignalan optional AbortSignal to abort the request
Create or update an identity provider configuration.
Token exchange involves exchanging an identity provider-signed token for a State Backed-signed token. By adding an identity provider configuration to State Backed, you are instructing State Backed to trust any valid token from that identity provider when evaluating whether to allow a token exchange. You are also extracting the claims from that token that you want to make available to your token providers to include in the State Backed token.
For example, if you are using Auth0 as your identity provider, you can configure State Backed to trust your Auth0 tokens by calling:
client.identityProviders.upsert({
aud: "https://<your-auth0-domain>.us.auth0.com/api/v2/",
iss: "https://<your-auth0-domain>.us.auth0.com/",
jwksUrl: "https://<your-auth0-domain>.us.auth0.com/.well-known/jwks.json",
algs: ["RS256"],
mapping: {
"sub.$": "$.sub",
"email.$": "$.email",
"provider": "auth0",
},
})
State Backed uses the audience (aud
) and issuer (iss
) claims in any tokens
provided for exchange to identify the identity provider to use for verification.
In this example, token providers would be have access to sub
, email
, and provider
claims that they could include in the resultant State Backed token.
Upserts may change algorithms, mappings, keys or jwksUrls.
This endpoint requires admin access.
identity provider configuration. At least one of aud
and iss
must be provided and at least one of keys
and jwksUrl
must be provided.
Allowed signing algorithms
Optional
aud?: stringThe audience claim that identifies tokens from this identity provider (one of aud or iss must be provided)
Optional
iss?: stringThe issuer claim that identifies tokens from this identity provider (one of aud or iss must be provided)
Optional
jwksAbsolute URL at which to find a JWKS key set to verify token signatures (one of key or jwksUrl must be provided)
Optional
key?: stringbase64url-encoded key to use to verify token signatures (one of key or jwksUrl must be provided)
A mapping object that extracts claims from the identity provider tokens that token providers can reference when creating the claims for State Backed tokens.
The values of properties that end in ".$" are treated as JSONPath references into the claim set of the provided token.
So a mapping of { "sub.$": "$.sub" }
with identity provider claims of { "sub": "user-123" }
will result in { "sub": "user-123" }
as the input claims into any token provider.
Optional
signal: AbortSignalan optional AbortSignal to abort the request
Private
inReadonly
keysOptional
scopes?: ("events.write" | "events.read" | "state.read" | "instances.read" | "instances.write" | "instances.admin" | "machines.read" | "machines.write" | "machines.admin" | "machine-versions.read" | "machine-versions.write" | "analytics.read" | "org.read" | "org.write" | "org.keys.write" | "org-members.write" | "logs.read" | "tokens.admin")[]The scopes that any request with a token signed by this key will have access to.
You must either pass scopes
or use
.
Optional
use?: "production" | "ci"The intended use for this key. This is a shorthand way to set a reasonable set of scopes.
You must either pass scopes
or use
.
Optional
signal: AbortSignalOptional
signal: AbortSignalOptional
opts: ListOptionsOptional
signal: AbortSignalPrivate
latestReadonly
logsLogs API.
State Backed collects logs from transitions, actions, services, authorizers, and migrations. Logs are currently available approximately 1 minute after they are generated and log retention depends on your plan.
Retrieve a batch of up to 100 log entries.
Each log entry may have multiple log lines in its log
field.
You may receive fewer than 100 log entries (or 0 entries) due to partitioning.
Along with the log entries, you will receive a maxTimestamp
field indicating
the timestamp to use as your from
parameter in your next call if you want to
retrieve the next batch of logs.
If the returned maxTimestamp
matches your from
parameter, you have retrieved
all of the logs that are currently available.
You should then wait 30s and try again if you want to retrieve more logs.
the timestamp to start retrieving logs from
Optional
filter: { optional filter parameters to filter the logs returned
Optional
instanceOptional
machineOptional
machineOptional
to?: DateOptional
signal: AbortSignalan optional AbortSignal to abort the request
logs
and maxTimestamp
Returns an async iterator that yields log entries as they are generated, polling in a sensible way for new entries.
the timestamp to start retrieving logs from
Optional
filter: { optional filter parameters to filter the logs returned
Optional
instanceOptional
machineOptional
machineOptional
to?: DateOptional
signal: AbortSignalan optional AbortSignal to abort the iteration. If aborted, the iterator will end and no error will be thrown.
An AsyncIterator that yields log entries as they are generated.
retrieve for more information on the parameters.
If no filter.to
is provided, the iterator will never end because it will
continue to look for new logs.
Example:
const logs = client.logs.watch(new Date());
for await (const log of logs) {
// do something with log
}
Readonly
machineMachine instances API.
Think of a machine definition like a class and machine instances as, well, instances of that class.
An instance of a machine has persistent state that preserves the state of the XState machine, including any context, history, etc.
You can create as many instances of each machine as you'd like. Each instance is independent. It has its own name, its own state, makes its own authorization decisions, receives its own events, and handles its own delayed events.
Retrieve the administrative state of a machine instance.
the name of the machine we are retrieving an instance of
the name of the machine instance we are retrieving
Optional
signal: AbortSignalan optional AbortSignal to abort the request
the administrative state of the machine
Update the desired machine version for an existing instance.
The instance will not be upgraded immediately but will be upgraded the next time an event is sent to it from a settled state.
the name of the machine we are updating the desired version for
the name of the machine instance we are updating the desired version for
desired version information
Optional
signal: AbortSignalan optional AbortSignal to abort the request
errors.NoMigrationPathError if there is no path through the set of existing migrations from the current instance version to the desired instance version.
Create a machine instance.
the name of the machine we are creating an instance of
instance information
Optional
context?: { The initial context for the machine instance.
Defaults to {}
.
Optional
machineOptional
signal: AbortSignalan optional AbortSignal to abort the request
the initial state and public context of the machine after initialization
The methods within machineInstances.dangerous are... DANGEROUS.
They are intended to be used in development or in very exceptional circumstances in production.
These methods can cause data loss and are the only mechanisms through which you can cause a machine instance to enter an invalid state.
Deletes a machine instance.
THIS WILL OBVIOUSLY CAUSE DATA LOSS
Deleted machine instances are not recoverable.
All historical transitions, scheduled events, pending upgrades, and current state will be irrevocably deleted.
the name of the machine we are deleting an instance of
the name of the machine instance we are deleting
confirmation that you are permanently deleting data
Optional
signal: AbortSignalan optional AbortSignal to abort the request
Pauses or resumes a machine instance.
PAUSE WITH CARE
Pausing a machine instance will cause it to reject all events until it is resumed, including rejecting scheduled/delayed events. Scheduled events are only retried 5 times (~30 seconds apart) before they are permanently dropped so it is possible to invalidate the typical guarantees that your machine provides by pausing an instance.
the name of the machine we are pausing/resuming an instance of
the name of the machine instance we are pausing/resuming
status information
Optional
signal: AbortSignalan optional AbortSignal to abort the request
Retrieve the machine instance's state and public context
the name of the machine we are retrieving an instance of
the name of the machine instance we are retrieving
Optional
signal: AbortSignalan optional AbortSignal to abort the request
the current state and public context of the machine
Returns an XState-compatible actor that represents the machine instance.
The actor allows for subscriptions to state and sending events.
the name of the machine we are creting an actor for
the name of the machine instance we are creating an actor for
Optional
signal: AbortSignalan optional AbortSignal to abort the request
Convenience method to ensure that a machine instance exists.
If the machine exists, it will read its state. Otherwise, it will create the machine and return its state.
the name of the machine we are ensuring exists
the name of the machine instance we are ensuring exists
parameters to use when creating the machine instance if it doesn't exist OR function returning those parameters if they are expensive to calculate
Optional
signal: AbortSignalan optional AbortSignal to abort the request
the current (or initial) state and public context of the machine
Returns an XState-compatible actor that represents the machine instance, creating the instance if it does not exist.
The actor allows for subscriptions to state and sending events.
the name of the machine we are creting an actor for
the name of the machine instance we are creating an actor for
parameters to use when creating the machine instance if it doesn't exist OR function returning those parameters if they are expensive to calculate
Optional
signal: AbortSignalan optional AbortSignal to abort the request
Retrieve a page of machine instances for a machine.
the name of the machine we are retrieving instances for
Optional
opts: ListOptionsoptions for the list operation
Optional
signal: AbortSignalan optional AbortSignal to abort the request
Retrieve a page of transitions for a machine instance.
the name of the machine we are retrieving transitions for
the name of the machine instance we are retrieving transitions for
Optional
opts: ListOptionsoptions for the list operation
Optional
signal: AbortSignalan optional AbortSignal to abort the request
Query for instances of this machine whose indexed context value matches the given query.
Results are returned in pages and the next page may be retrieved by passing the
cursor
returned by the prior call and supplying the same parameters.
Note: The same instance may appear on multiple pages of the result set if its indexed context value changes between calls.
the name of the machine we are querying instances of
the name of the index we are querying
Optional
req: { the query parameters, will list all machine instances in ascending order if not provided
Optional
cursor?: stringThe cursor returned from a previous call to query.
Optional
dir?: "desc" | "asc"The sort direction for the index.
Optional
limit?: numberThe maximum number of items to return.
Optional
op?: "eq" | "ne" | "gt" | "gte" | "lt" | "lte"The operation for the filter.
Optional
value?: stringThe value for the filter.
Optional
signal: AbortSignalan optional AbortSignal to abort the request
Send an event to a machine instance.
the name of the machine we are sending an event to
the name of the machine instance we are sending an event to
event information
Optional
signal: AbortSignalan optional AbortSignal to abort the request
the state and public context of the machine after processing the event
Subscribe to state change notifications for an instance.
onStateUpdate
will be invoked right after the subscription is confirmed and
on (almost) every state update thereafter until unsubscribe is called.
It is possible that clients may miss some state updates (e.g. due to transitions happening during reconnects) so the only assumption client code should make is that onStateUpdate is called with the latest known state.
A web socket will be established and kept open whenever at least one subscriber is active.
In non-web environments, you may need to set the WebSocket implementation the client uses by passing a WebSocket option in the constructor.
the name of the machine we are subscribing to an instance of
the name of the instance we are subscribing to
function to invoke with each state update
Is the state machine complete
Optional
publicThe public context of the machine instance.
This includes all context under the public
key.
Array of tags for the current states
Timestamp for when the state was created
Optional
onError: ((err) => void)function to invoke if there is an error subscribing
Optional
signal: AbortSignaloptional AbortSignal. If aborted, we will unsubscribe.
an unsubscribe function to be called when the subscription should be canceled
Readonly
machineMachine version migrations API.
Migrations allow you to migrate running instances from one machine version to another.
A machine version migration maps states and context from one machine version to another.
Similarly to machine versions, machine version migrations are created in a 3-step process: provisional creation to reserve an ID, code upload, and finalization.
However, you can use the create
convenience wrapper to do all 3 steps in one call.
Convenience method to create a machine version migration in one call.
Once a machine version migration is finalized, it may participate in upgrade operations on existing instances.
the name of the machine we are adding a version to
migration information
Optional
signal: AbortSignalan optional AbortSignal to abort the request
machine version migration ID
Finalize the creation of a machine version migration.
Once a machine version migration is finalized, it may participate in upgrade operations on existing instances.
the name of the machine we are finalizing a version for
the signed machine version migration ID returned from the provisional creation step
Optional
signal: AbortSignalan optional AbortSignal to abort the request
machine version migration ID
Provisionally create a machine version migration.
After this call, you must upload your code and finalize the machine version migration like this:
const { codeUploadFields, codeUploadUrl } = await provisionalVersionMigrationCreationResponse.json();
const uploadForm = new FormData();
for (const [key, value] of Object.entries(codeUploadFields)) {
uploadForm.append(key, value as string);
}
uploadForm.set("content-type", "application/javascript");
uploadForm.append(
"file",
new Blob(["javascript-code-here"], {
type: "application/javascript",
}),
"your-file-name.js",
);
const uploadRes = await fetch(
codeUploadUrl,
{
method: "POST",
body: uploadForm,
},
);
the name of the machine we are adding a version migration to
migration information
Optional
signal: AbortSignalan optional AbortSignal to abort the request
code upload fields and url to upload the machine version migration's code to and a signed machine version migration ID to use in the finalization step
Readonly
machineMachine versions API.
Each machine definition may have many machine versions associated with it.
The most important aspect of a machine version is your actual code for your authorizer and state machines.
Machine versions can also provide a version specifier to help you link a version to your own systems. We recommend a semantic version, timestamp, or git commit sha for a version specifier.
Machine versions are created in a 3-step process: provisional creation to reserve an ID, code upload, and finalization.
You can use the convenience wrapper, create
, to do all 3 steps in one call.
If you want to migrate running instances from one version to another,
Convenience method to create a machine version in one call.
Once a machine version is created, you may create instances from it. If you want to migrate running instances from one version to another,
the name of the machine we are adding a version to
version information
Optional
signal: AbortSignalan optional AbortSignal to abort the request
machine version ID
machineVersionMigrations. If you want all future instances to use this version by default, pass { makeCurrent: true }.
Finalize the creation of a machine version.
Once a machine version is finalized, you may create instances from it. If you want to migrate running instances from one version to another,
the name of the machine we are finalizing a version for
the signed machine version ID returned from the provisional creation step
version information
Optional
clientInformational only. Any string that describes this version. Good uses would be a semantic version number or git commit.
Optional
indexMapping from index names (must match index names from the corresponding machine) to JSON path selectors into machine context. On every state update, the pointed-to value in machine context will be extracted and used to index the machine.
Optional
makeWhether to make this version the current version for the machine definition.
If true
, the current version will be set to this version.
If false
, the current version will not be changed.
Optional
signal: AbortSignalan optional AbortSignal to abort the request
machine version ID
machineVersionMigrations. If you want all future instances to use this version by default, pass { makeCurrent: true }.
Retrieve a page of machine versions for a machine.
the name of the machine we are retrieving versions for
Optional
opts: ListOptionsoptions for the list operation
Optional
signal: AbortSignalan optional AbortSignal to abort the request
Provisionally create a machine version.
After this call, you must upload your code and finalize the machine version like this:
const { codeUploadFields, codeUploadUrl } = await provisionalVersionCreationResponse.json();
const uploadForm = new FormData();
for (const [key, value] of Object.entries(codeUploadFields)) {
uploadForm.append(key, value as string);
}
uploadForm.set("content-type", "application/javascript");
uploadForm.append(
"file",
new Blob(["javascript-code-here"], {
type: "application/javascript",
}),
"your-file-name.js",
);
const uploadRes = await fetch(
codeUploadUrl,
{
method: "POST",
body: uploadForm,
},
);
the name of the machine we are adding a version to
Optional
signal: AbortSignalan optional AbortSignal to abort the request
code upload fields and url to upload the machine version's code to and a signed machine version ID to use in the finalization step
machineVersionMigrations.
Readonly
machinesMachines API.
Machine definitions name a logical machine.
For example, you might have a machine definition that represents a flow for a user in your app (like the onboarding machine) or a machine definition that represents the state of a user or entity (like a user machine or a machine for a document that might be shared across many users).
We call this a logical machine because your actual business logic lives in machine versions.
Once a machine exists and it has at least one version, you can launch instances of it.
Create a machine.
the name of the machine
Optional
req: Omit<{ additional options for the machine creation request
Optional
signal: AbortSignalan optional AbortSignal to abort the request
The methods within machines.dangerous are... DANGEROUS.
They are intended to be used in development or in very exceptional circumstances in production.
These methods can cause data loss.
Deletes a machine.
THIS WILL OBVIOUSLY CAUSE DATA LOSS
Deleted machines are not recoverable and deleting a machine deletes its associated versions and the migrations between them.
Machines cannot be deleted if there are still instances of them running. You may delete instances of machines using
the name of the machine we are deleting an instance of
confirmation that you are permanently deleting data
Optional
signal: AbortSignalan optional AbortSignal to abort the request
machineInstances.dangerously.delete.
Retrieve a machine definition.
the name of the machine we are retrieving
Optional
signal: AbortSignalan optional AbortSignal to abort the request
the machine definition
Retrieve a page of machine definitions.
Optional
opts: ListOptionsoptions for the list operation
Optional
signal: AbortSignalan optional AbortSignal to abort the request
a page of machine definitions
Private
Readonly
optsOptional
actReadonly
orgsOptional
allowIf true, a key, trusted identity provider, and token provider
that support anonymous access will be created for the org.
The usual authorization checks still apply at the machine level
so individual reads and writes for anonymous access depends on
your allowRead
and allowWrite
implementations.
Auth context for anonymous tokens includes Session ID (sid
),
Device ID (did
), and { "auth": "anonymous" }
.
true
Optional
signal: AbortSignalOptional
opts: ListOptionsOptional
signal: AbortSignalPrivate
tokenConfiguration to retrieve the State Backed token to use for all requests.
Private
tokenReadonly
tokenToken exchange involves exchanging an identity provider-signed token for a State Backed-signed token.
Token providers are responsible for creating State Backed tokens from a standardized claim set extracted from identity provider tokens by their mappings.
Token providers are identified by a service name. You might, for instance, want a service name for each application that you host with State Backed.
Token providers also specify the State Backed key to use to sign the tokens they generate and a mapping that creates the claims for the generated token.
For example, if your identity provider mappings extract claims like this:
{
"sub": "your-sub",
"email": "your-email",
"provider": "identity-provider"
}
you could create a token provider like this:
client.tokenProviders.upsert({
"keyId": "sbk_...", // ID for a previously-created State Backed key
"service": "your-app", // any identifier for your token provider
"mapping": {
"sub.$": "$.sub",
"email.$": "$.email",
"provider.$": "$.provider",
}
})
That token provider would allow you to exchange any of your identity provider-
signed tokens for a State Backed token that includes the sub, email, and provider
claims, all of which would be available for your use in allowRead
and allowWrite
functions in your machine definitions.
Upserts may change key ids and mappings.
Delete the token provider configuration identified by its service name.
the service name of the token provider to delete
Optional
signal: AbortSignalan optional AbortSignal to abort the request
Retrieve a page of token providers.
Optional
opts: ListOptionsoptions for the list operation
Optional
signal: AbortSignalan optional AbortSignal to abort the request
Create or update a token provider configuration.
The mapping is an object that defines the shape of the claims that will be included in any State Backed tokens generated by this token provider. The mapping may refer to claims extracted from the identity provider token by suffixing the key with ".$" and using a JSON path to the claim in the identity provider token.
For example:
{
"sub.$": "$.sub",
"service": "my-service",
}
would produce a sub claim with the value of the sub
field on the extracted claims
and a service claim with the constant value "my-service".
token provider configuration
ID of the State Backed key (created using smply keys create or posting to /keys) to use to sign tokens created by this token provider.
A mapping object that creates the claim set for the State Backed token and may reference the claims extracted by the identity provider mappings.
The values of properties that end in ".$" are treated as JSONPath references into the claim set of the provided token.
So a mapping of { "sub.$": "$.sub" }
with identity provider claims of { "sub": "user-123" }
will result in { "sub": "user-123" }
as the State Backed token claims.
The name of this token provider. This name is used to request tokens from the /tokens endpoint
Optional
signal: AbortSignalan optional AbortSignal to abort the request
Readonly
tokensOptional
signal: AbortSignalPrivate
wsPrivate
headersPrivate
nonOptional
x-Optional
x-Private
ensurePrivate
refreshPrivate
setPrivate
tokenPrivate
tokenGenerated using TypeDoc
A client for the StateBacked.dev API.
State Backed allows you to launch instances of XState state machines in the cloud with a simple API.
This client is suitable for use client-side or server-side.
See the full State Backed documentation at https://docs.statebacked.dev.
To use this client, first, download the smply CLI with
npm install --global smply
. Get your organization ID withsmply orgs list
. Use anonymous authentication with just your org ID or configure token exchange to authenticate users using your existing identity provider.Then, create a State Backed client with
new StateBackedClient(config)
;