Skip to main content

Export Resources

Use the export API to retrieve ThunderID resources:

  • POST /export: returns a JSON object.

JSON Response Shape​

POST /export returns this payload:

json
{
"resources": "# File: My_App.yaml\napiVersion: thunder/v1\n...",
"environment_variables": "APPLICATION_MY_APP_CLIENT_ID=\nAPPLICATION_MY_APP_CLIENT_SECRET=\n"
}

Field behavior:

  • resources: Combined YAML output for all exported resources, with # File: headers and --- separators.
  • environment_variables: environment file content with one assignment per detected template variable. A variable is left empty, except one for a list the resource does not have, such as an application's redirectUris when it has none, which is written as [] so the file imports as it is.

If the export has no template variables, environment_variables is an empty string.

Organization units come out in the same order every time: each unit before the units under it, units under the same parent by name, and each unit once however it is reached. Exporting units that have not changed therefore gives the same text.

Template Variable Names​

Each parameterized field becomes a template variable named after the resource type, the resource name and the field, in uppercase. The clientId field of an application named My App becomes APPLICATION_MY_APP_CLIENT_ID.

The resource type leads the name because a name is only unique within its own type. An application and an agent may both be called Dummy, and without the type both would claim DUMMY_CLIENT_ID. One value would win and the other resource would import with the wrong credential.

ThunderID normalizes the resource name so that the generated name is valid in a template placeholder:

  • Every character that is not a letter or a digit becomes an underscore, and consecutive underscores collapse into one.
  • Leading and trailing underscores are removed, so a name ending in a separator produces the same variable name as the name without it.
  • A name that would start with a digit gets a leading underscore. The resource type leads every generated name, so this applies only where a name is derived without one.

Normalization applies to generated variable names only. Exported file names and the name field inside the exported YAML keep the original resource name.

Resource typeResource nameVariable name for clientId
applicationMy AppAPPLICATION_MY_APP_CLIENT_ID
applicationMy-AppAPPLICATION_MY_APP_CLIENT_ID
applicationMy App-APPLICATION_MY_APP_CLIENT_ID
application2FA AppAPPLICATION_2FA_APP_CLIENT_ID
agentMy AppAGENT_MY_APP_CLIENT_ID

Because normalization maps several names onto the same prefix, two resources of one type in a single export can compete for the same variable name. In that case, the second resource gets a numeric suffix. Exporting both Wayfinder-Concierge and Wayfinder_Concierge produces APPLICATION_WAYFINDER_CONCIERGE_CLIENT_ID and APPLICATION_WAYFINDER_CONCIERGE_2_CLIENT_ID, so each resource keeps its own value in the environment file.

Updating an Existing Environment File​

Variable names generated before the resource type was added carry no type prefix. An environment file kept from an earlier export sets names such as MY_APP_CLIENT_ID, which a current export no longer asks for. Rename each entry to include its resource type, or export again and fill in the new file.

User Credentials​

Every user is exported, whether or not it has a password. A user who has one carries it as a template variable rather than a value:

yaml
credentials:
password: "{{.USER_ALICE_EXAMPLE_COM_PASSWORD}}"

A stored password is a one-way hash, so the original cannot be exported. Naming it here means the importing server supplies the password from its own environment or secret provider and hashes it on the way in, which leaves the imported user able to sign in. Without the placeholder the user would import with no credential at all.

Which credentials a user carries depends on its user type. The export includes each credential the user type declares, such as password, when the user has set it. A credential the user has not set is left out, so a user created without a password exports with no credentials block, and the import asks for nothing it would never use. A credential outside the user type, such as a passkey, is never exported: it is bound to a device and means nothing on another deployment.

A user with no username exports no credentials, because the variable is named after the username and there is nothing to name it after.

The password placeholder is named directly from the username, so it does not take the numeric suffix that resolves competing names for other fields. Two users whose usernames normalize to the same name, such as alice@example.com and alice.example.com, would therefore claim one password variable and both import with the same password.

ThunderID refuses the whole export in that case, with the error EXP-1003 naming the two resources. The bundle is not returned at all, because one that dropped a resource silently would look complete. Rename one of the users, or export them separately.

Resource Server Identifiers​

A resource server's identifier is the audience it is served under, such as an API's base URL or an MCP server's URL, and each deployment usually serves it under its own. The identifier is exported as a template variable named like any other field, so a resource server named Orders API exports:

yaml
identifier: {{.RESOURCE_SERVER_ORDERS_API_IDENTIFIER}}

Its resources, actions, and delimiter are exported as they are.

Exports From a Control Plane​

What an export contains depends on the plane you export from. A data plane holds its own values, so each parameterized field carries a template placeholder, and environment_variables lists the placeholders for you to fill in. A control plane authors configuration but does not hold the values it refers to. Each parameterized field carries a reference instead, naming where a data plane holds the value, and there is nothing to fill in.

The same application exported from each plane:

yaml
# From a data plane
oauth:
clientId: {{.APPLICATION_MY_APP_CLIENT_ID}}
clientSecret: {{.APPLICATION_MY_APP_CLIENT_SECRET}}

# From a control plane
oauth:
clientId: var:APPLICATION_MY_APP_CLIENT_ID
clientSecret: sec:APPLICATION_MY_APP_CLIENT_SECRET

A reference names one of two collections:

PrefixRefers toExample
var:An ordinary value, such as a client IDvar:APPLICATION_MY_APP_CLIENT_ID
sec:A credential, such as a client secretsec:APPLICATION_MY_APP_CLIENT_SECRET

A list, such as an application's redirect URIs, exports as a list holding one var: reference. The variable it names holds the items, as described in Value References. An empty list exports as it is, with no reference.

The prefix is what keeps a credential out of a read. A data plane returns a variable's value when asked for it, and never returns a secret's. A client secret, a connection's secret or token, and any property marked isSecret always export with sec:.

Stored References Keep Their Names​

A field that already holds a reference exports as it stands. The name in a reference records where the value went, so renaming the resource does not change it. An application renamed from Old Name to New Name still exports sec:APPLICATION_OLD_NAME_CLIENT_SECRET, because that is the name the data plane holds the secret under.

Each entry in a list gets the same treatment on its own. In an application with two inbound configurations, a reference already placed in one is kept, and a value in the other is replaced with a new reference.

What a Control Plane Does Not Parameterize​

A user's credentials are written as template placeholders on either plane, as described in User Credentials. A control-plane export that includes users who have set a password therefore still lists a password variable for each of them in environment_variables. Every other control-plane export leaves environment_variables empty.

A Credential That Refers to a Variable​

ThunderID refuses to export a credential that refers to an ordinary variable, such as a client secret holding var:APPLICATION_MY_APP_CLIENT_SECRET. Exporting it as it stands would point the credential at a value a read returns. Changing the prefix to sec: would name a secret that was never stored.

The export leaves that resource out and logs a warning naming it. The other resources export as usual. Update the field to a sec: reference that names the stored secret, then export again.

Internal API Model Reference​

The API reference schema also defines an internal ExportResponse model (see ExportResponse.envFile, backed by the EnvironmentFile schema/struct):

json
{
"files": [
{
"fileName": "google-idp.yaml",
"content": "resource_type: connection\ntype: google\n...",
"size": 128
}
],
"envFile": {
"fileName": ".env",
"content": "CONNECTION_GOOGLE_CLIENT_ID=\nCONNECTION_GOOGLE_CLIENT_SECRET=\n",
"size": 62
},
"summary": {
"totalFiles": 2,
"totalSizeBytes": 190
}
}

When no template variables are detected, envFile is omitted (or null in internal JSON serialization paths).

Format Option​

In options.format, only yaml is currently supported for generated resource content.

Explore with AI

ThunderID LogoThunderID Logo

Product

DocsAPIsSDKs
© Copyright Linux Foundation Europe.For web site terms of use, trademark policy and other project policies please see https://linuxfoundation.eu/en/policies.