Skip to navigation

Importing products

Preview a product from a JSON document, then create it in your account. The dashboard import page uses the same endpoints that this guide describes.

Before you begin

  • To create a product, you need a Runtype API key. For more information, see Authentication.
  • The preview endpoints don’t require authentication.

Supported sources

The import APIs accept these JSON sources:

  • Agent-to-Agent (A2A) agent cards.
  • Raw Full Product Object (FPO) JSON.
  • FPO template JSON.

The import APIs reject these sources:

  • GitHub repository homepages.
  • README and Markdown URLs.
  • Raw JSON passed through query parameters.
  • Generic website or repository crawling.

Use GitHub URLs only for specific JSON files. The import service converts GitHub blob URLs to raw file URLs before it fetches them. It accepts raw GitHub file URLs as they are. For a gist, use a raw gist file URL that points to one JSON file.

A source URL must use https and respond with a Content-Type of application/json or text/plain, and the document must be 256 KB or smaller. The same size limit applies to pasted JSON.

Supported versions

The following table lists the version values that each source type accepts:

Source typeAccepted version valuesNotes
Raw FPO1.0, 1.1, 2.02.0 is the current version. An inline agent keeps its runtime fields under agent.config.
FPO templateTop level: 1.0, 1.1. Nested productObject.version: 1.0, 1.1, 2.0The nested product object follows the raw FPO rules.

At 1.0 and 1.1, an inline agent keeps its runtime fields, such as model, directly on the agent object.

Import flow

To import a product, follow these steps:

  1. Preview the source with POST /v1/quick-start/imports/preview.
  2. Optional: Reload the preview with GET /v1/quick-start/imports/:token.
  3. Create the product with POST /v1/quick-start/create.
  4. Finish setup in the dashboard.

Step 1: Preview an import source

Choose a hosted URL or paste the JSON document into the request body.

Preview a hosted JSON document

To preview a public JSON file, send a URL source. The following TypeScript example sends the request:

TypeScript
const previewResponse = await fetch('https://api.runtype.com/v1/quick-start/imports/preview', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
source: {
kind: 'url',
url: 'https://example.com/YOUR_PRODUCT.json',
},
}),
})
const preview = await previewResponse.json()
console.log(preview.importToken)
console.log(preview.sourceType) // "fpo"
console.log(preview.preview.productName)

Replace https://example.com/YOUR_PRODUCT.json with the public URL of your FPO, FPO template, or agent card.

The following cURL command sends the same request:

cURL
curl https://api.runtype.com/v1/quick-start/imports/preview \
-H "Content-Type: application/json" \
-d '{
"source": {
"kind": "url",
"url": "https://example.com/YOUR_PRODUCT.json"
}
}'

Preview pasted JSON

To preview a document that you already have in memory, send a JSON source with its contents in content. The following TypeScript example reads a template file from your app and submits it:

TypeScript
const templateDocument = await fetch('/YOUR_TEMPLATE_FILENAME.json').then((response) =>
response.text()
)
const previewResponse = await fetch('https://api.runtype.com/v1/quick-start/imports/preview', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
source: {
kind: 'json',
label: 'Customer Support Template',
content: templateDocument,
},
}),
})
const preview = await previewResponse.json()
console.log(preview.sourceType) // "fpo-template"
console.log(preview.template?.variables)

Replace YOUR_TEMPLATE_FILENAME with the filename that your app serves.

The following cURL command sends a template as a JSON string in content:

cURL
curl https://api.runtype.com/v1/quick-start/imports/preview \
-H "Content-Type: application/json" \
-d @- <<'EOF'
{
"source": {
"kind": "json",
"label": "Customer Support Template",
"content": "{\"version\":\"1.1\",\"productObject\":{\"version\":\"2.0\",\"product\":{\"name\":\"{{productName}}\",\"description\":\"Support automation for {{companyName}}\"},\"capabilities\":[{\"id\":\"cap_support\",\"name\":\"Support Agent\",\"description\":\"Handle incoming support requests.\",\"agent\":{\"name\":\"{{productName}} Agent\",\"description\":\"Handle support requests for {{companyName}}.\",\"config\":{\"model\":\"claude-sonnet-5\"}}}],\"tools\":[],\"surfaces\":[{\"id\":\"surface_chat\",\"name\":\"{{productName}} Chat\",\"type\":\"chat\",\"config\":{},\"routes\":[{\"capabilityId\":\"cap_support\"}]}],\"_meta\":{\"schemaVersion\":\"1.0\",\"catalogVersion\":\"1.0\",\"generatedAt\":\"2026-03-07T00:00:00.000Z\",\"generatorVersion\":\"1.0.0\",\"planHash\":\"import-json-example\"}},\"template\":{\"variables\":[{\"key\":\"productName\",\"label\":\"Product Name\",\"inputType\":\"text\",\"required\":true,\"defaultValue\":\"Example Organization Support Copilot\"},{\"key\":\"companyName\",\"label\":\"Company Name\",\"inputType\":\"text\",\"required\":true}]}}"
}
}
EOF

The content string declares two template variables, productName and companyName. Only productName has a default value.

Preview an A2A agent card

An A2A agent card is a JSON document with a top-level name and optional fields such as description, url, and skills. Send it as a URL or pasted JSON source, the same way as an FPO. The preview response returns sourceType: "a2a-agent".

Preview response

The preview response describes the product before anything is created. The following table lists the fields to check:

FieldSource typesDescription
importTokenAllToken for the reload and create requests. It expires after 30 minutes.
sourceTypeAlla2a-agent, fpo, or fpo-template.
previewAllproductName, description, capabilities (each with type and name), toolCount, and surfaceCount.
architectureAllThe agents, flows, tools, and surfaces that the create request builds.
pendingSecretsfpo, fpo-templateCredentials that the product’s tools need, with toolName, key, required, and optional description and docsUrl. Present only when a tool needs setup.
template.variablesfpo-templateThe template’s variables and their input types, defaults, and required flags.
template.defaultsSufficientfpo-templatetrue when the default values alone produce a valid product.
a2aa2a-agentThe agent card and the product template that Runtype builds around it.

If template.defaultsSufficient is true, you can create the product without a variables object. If pendingSecrets is present, have those credentials ready before you finish setup.

Step 2: Reload a preview session

Use the importToken from the preview response to restore the preview after an authentication redirect or page refresh.

The following TypeScript example restores the preview session:

TypeScript
const session = await fetch(
'https://api.runtype.com/v1/quick-start/imports/qsi_YOUR_IMPORT_TOKEN'
).then((response) => response.json())
console.log(session.importToken)
console.log(session.architecture)

Replace qsi_YOUR_IMPORT_TOKEN with the token returned by the preview request.

The following cURL command restores the same preview session:

cURL
curl https://api.runtype.com/v1/quick-start/imports/qsi_YOUR_IMPORT_TOKEN

The response has the same shape as the preview response. Preview sessions expire after 30 minutes. When the token doesn’t identify a stored session, the API returns 404 with the code SESSION_NOT_FOUND.

Step 3: Create the product

Use the import token to create the product after you accept the preview.

Create a product from a raw FPO

To create a raw FPO import, send the importToken in a request that includes your API key. The following TypeScript example creates the product:

TypeScript
const createResponse = await fetch('https://api.runtype.com/v1/quick-start/create', {
method: 'POST',
headers: {
Authorization: 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
importToken: 'qsi_YOUR_IMPORT_TOKEN',
}),
})
const created = await createResponse.json()
console.log(created.redirectUrl)

Replace YOUR_API_KEY with your Runtype API key and qsi_YOUR_IMPORT_TOKEN with the preview token.

The following cURL command creates the same raw FPO import:

cURL
curl https://api.runtype.com/v1/quick-start/create \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"importToken": "qsi_YOUR_IMPORT_TOKEN"
}'

Create a product from an FPO template

To create an FPO template import, send values for required template variables that don’t have defaults. The following TypeScript example sends the required values:

TypeScript
const created = await fetch('https://api.runtype.com/v1/quick-start/create', {
method: 'POST',
headers: {
Authorization: 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
importToken: 'qsi_YOUR_TEMPLATE_IMPORT_TOKEN',
variables: {
companyName: 'Example Organization',
},
}),
}).then((response) => response.json())
console.log(created.product.id)
console.log(created.redirectUrl)

Replace YOUR_API_KEY with your Runtype API key and qsi_YOUR_TEMPLATE_IMPORT_TOKEN with the preview token. If your template declares more variables, include their values under variables.

The following cURL command creates the same FPO template import:

cURL
curl https://api.runtype.com/v1/quick-start/create \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"importToken": "qsi_YOUR_TEMPLATE_IMPORT_TOKEN",
"variables": {
"companyName": "Example Organization"
}
}'

Variables with inputType: "secret" can’t have default values. Runtype substitutes a secret variable’s value into the product and stores it in the product record. To keep a credential in your secrets instead, declare it as a pending secret on the tool that uses it. For more information, see Collect credentials.

Create a product from an A2A agent card

An A2A import accepts an optional productName field that overrides the name from the agent card. The name must be 1 to 255 characters. The following cURL command creates an A2A import with a custom name:

cURL
curl https://api.runtype.com/v1/quick-start/create \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"importToken": "qsi_YOUR_A2A_IMPORT_TOKEN",
"productName": "Research Assistant"
}'

For an FPO or FPO template import, productName returns a 400 error. Set the product name in the document instead.

Create response

A successful create returns 201. The following table lists the response fields:

FieldTypeDescription
successBooleanAlways true on success.
productObjectThe new product’s id, name, and description.
capabilitiesArrayEach capability’s id, type, and name, plus agentId or flowId for the agent or flow created.
redirectUrlStringThe dashboard path to open next. See Step 4.
estimatedSetupSecondsNumberEstimated setup time.
testApiKeyObjectA new test API key, with key, prefix, and limits. Absent if the key couldn’t be created.

Each successful create issues a new test API key. The key allows 20 executions a day and 200 in total. Store the key value if you plan to call the product with it.

Step 4: Finish setup

The redirectUrl value is a path in the dashboard, not a full URL. To finish setup, open https://use.runtype.com followed by the path.

If a tool in the product needs credentials that you haven’t set up yet, the path opens the secrets configuration page instead of the product. Enter the listed secrets before you test the product. For more information, see Managing secrets.

Required API key scopes

A dashboard session can create any import. An API key must hold the scopes for everything the product creates:

ConditionRequired scope
AlwaysPRODUCTS:CREATE or PRODUCTS:WRITE
The product declares secrets (product-level secrets, or a tool whose auth has setupRequired: true and secrets)SECRETS:WRITE
A capability creates a flowFLOWS:WRITE
A capability creates an agentAGENTS:WRITE or AGENTS:CREATE
The import is an A2A agent cardAGENTS:WRITE or AGENTS:CREATE
The import is an A2A agent card that uses the a2a-agent template (the default), which creates chat, API, and MCP surfacesPRODUCTS:SURFACES:WRITE
The product has surfacesPRODUCTS:SURFACES:WRITE
The product has schedulesSCHEDULES:WRITE
The product has recordsRECORDS:WRITE
The product has evalsEVALS:WRITE
The product has skillsSKILLS:WRITE
An HTTP flow step (fetch-url, api-call, wait-until, or paginate-api) references {{secret:NAME}}SECRETS:READ

Entities with createPolicy: "skip" do not need their scope. Test keys (rt_test_ prefix) cannot hold SECRETS:WRITE, so a test key cannot create a product that declares secrets. Use a live key with SECRETS:WRITE, or create the product from the dashboard.

Errors

If the request has no valid credential, the API returns HTTP 401 with the UNAUTHORIZED code:

{
"success": false,
"error": "Authentication required",
"code": "UNAUTHORIZED"
}

If the API key does not hold a required scope, the API returns HTTP 403 with the FORBIDDEN code. The error field names the missing scopes, and details.missingScopes lists them. Each inner list holds scopes of which the key needs one:

{
"success": false,
"error": "Insufficient permissions. This FPO requires: FLOWS:WRITE, SCHEDULES:WRITE",
"code": "FORBIDDEN",
"details": { "missingScopes": [["FLOWS:WRITE"], ["SCHEDULES:WRITE"]] }
}

The API creates nothing when it returns 403.

Create a repository button

To add a Deploy to Runtype link to a repository README, link to the import page with your document’s URL in the from query parameter. URL-encode the document URL. The following Markdown snippet creates the link:

[Deploy to Runtype](https://use.runtype.com/now?from=https%3A%2F%2Fexample.com%2FYOUR_PRODUCT.json)

To prefill a template variable, add a templateParam:VARIABLE_KEY query parameter for each value. URL-encode the colon as %3A. The following link prefills companyName:

[Deploy to Runtype](https://use.runtype.com/now?from=https%3A%2F%2Fexample.com%2FYOUR_TEMPLATE.json&templateParam%3AcompanyName=Acme)

The import page ignores prefilled values for secret variables.

Troubleshooting

Error responses carry a code field, an error message, and, when relevant, a details array. The following table lists the preview errors:

CodeCauseFix
FETCH_FAILEDRuntype couldn’t reach the URL.Check that the host is public and online.
GITHUB_SOURCE_NOT_SUPPORTEDThe URL points to a GitHub repository, directory, or gist page.Use the URL of one JSON file.
INVALID_AGENT_CARDThe document isn’t an agent card, FPO, or FPO template.Check details for the fields that failed validation.
INVALID_CONTENT_TYPEThe URL responded with a type other than application/json or text/plain.Serve the file as JSON or plain text.
INVALID_FPO_TEMPLATEThe document has productObject and template but isn’t a valid template.Check details for the validation errors.
INVALID_JSONThe source isn’t valid JSON.Validate the document with a JSON linter.
INVALID_REQUESTThe request body isn’t valid JSON.Check the request body.
INVALID_URLThe URL is malformed, doesn’t use https, or points to a blocked address.Use a public https URL.
MARKDOWN_NOT_SUPPORTEDThe URL points to a Markdown file.Use a JSON document URL.
RATE_LIMITEDYour IP address sent too many preview requests (429).Wait for the number of seconds in the Retry-After header.
SOURCE_TOO_LARGEThe document is larger than 256 KB.Reduce the document size.
URL_NOT_ACCESSIBLEThe URL returned an error status, such as 404 for a private file.Make the file public.
VALIDATION_ERRORThe source object is missing, or its kind, url, or content field is invalid.Check details for the field that failed.

The following table lists the create errors:

StatusCodeCauseFix
400INVALID_REQUESTThe body is invalid, productName was sent for a non-A2A import, or the template values produced an invalid FPO.Check error and details.
400VALIDATION_FAILEDA required template variable has no value, or the product failed validation.For missing variables, send the keys listed in details under variables.
401UNAUTHORIZEDThe request has no valid API key.Send Authorization: Bearer YOUR_API_KEY.
403NoneThe account was created by an agent and isn’t verified yet. The error field is account_verification_required.Follow the nextAction in the response.
404IMPORT_SESSION_NOT_FOUNDThe import token expired or doesn’t exist.Run the preview again and use the new token.
500CREATION_FAILEDRuntype couldn’t build the product.Try again. If the error repeats, contact support.

Next steps

  • FPO templates: define reusable product templates with user-provided values.
  • Runtype MCP server: import a product from an AI agent with the create_product_from_example tool and its url and variables inputs.
  • Quickstart: make your first Runtype API call.