THINKHX

Apps

An app is a reusable application: a model, a set of input fields your caller fills in, and the instructions sent to the model. You create apps through this resource, then run them through Runs. An app is private to your project until you publish it, at which point it also appears in the Catalog.

Endpoints

MethodPathScope
POST/v1/app/createapp:write
GET/v1/app/listapp:read
GET/v1/app/detail/<app_id>app:read
PATCH/v1/app/detail/<app_id>app:write
DELETE/v1/app/detail/<app_id>app:write

<app_id> is an app identifier, prefixed mapp_. Editing and deleting both act on the detail path; there is no separate update or delete path.

The app object

FieldTypeDescription
idstringThe app identifier, prefixed mapp_.
objectstringAlways app.
namestringThe app's name.
descriptionstringWhat the app does.
typestringprivate or public. A public app is listed in the catalog.
statusstringdraft or activated. Only an activated app can be run.
logostringThe identifier of the app's logo file, or an empty string.
modelstringThe model the app runs on.
model_librarystringThe exact model build resolved for this app.
dataarrayThe input schema. One object per field the caller fills in.
instructionarrayThe instructions sent to the model. null when you do not own the app.
runsobjectRun counters, as private and public.
tokensobjectTokens the app has consumed, as input, output and total, or null.
created_atintegerCreation time, in Unix seconds.
updated_atintegerLast change, in Unix seconds.

Each entry of data describes one input field:

FieldTypeDescription
idstringThe field identifier, prefixed madi_.
namestringThe field's name. This is the key you send when you launch a run.
typestringThe field's data type, as its identifier (prefixed mdti_). See Data field types.
placeholderstringThe hint shown to whoever fills the field in.
requiredbooleanWhether a run must supply a value.

runs and tokens answer two different questions: how often the app was launched, and what those launches spent. tokens covers the app's whole life, not the current billing cycle, and counts your project's own runs of it — so reading someone else's public app reports what you spent on it. Runs that ended in an error are left out, which is what makes the total match the figure the workspace shows for the same app. See Quota and token usage for the project-wide cycle figures.

Notetokens is null, rather than three zeros, when the project's runs carry no token measurement at all. An app that exists but has never run answers 0 on all three.

Create an app

POST /v1/app/create needs a name, a description, at least one input field and at least one instruction.

ParameterTypeRequiredDescription
namestringyesThe app's name.
descriptionstringyesWhat the app does.
categorystringnoThe task category used to pick a model. Also accepted as task_type or model_task_type.
dataarrayyesThe input schema. Each object needs a non-empty type and name, and may set placeholder and required. See Data field types below.
instructionarrayyesEach object needs a non-empty type and an instruction (also accepted as prompt).
statusstringnodraft or activated. Defaults to activated.
typestringnoprivate or public. Defaults to private.
curl
curl -X POST https://api.thinkhx.com/v1/app/create \
  -H "Authorization: Bearer sk-project-YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Support triage",
    "description": "Sorts an inbound support message by urgency.",
    "category": "text",
    "data": [
      { "type": "input", "name": "message", "placeholder": "Paste the message", "required": true }
    ],
    "instruction": [
      { "type": "system", "instruction": "Classify the message as low, normal or urgent." }
    ]
  }'
json
{
  "code": 200,
  "title": "OK",
  "response": {
    "id": "mapp_0ceacb46e5b3a99e91b6",
    "object": "app",
    "name": "Support triage",
    "description": "Sorts an inbound support message by urgency.",
    "category": "text",
    "model": "modi_7b1e4c2a9d05f3618ea4",
    "model_library": "mlyi_2c9a7f45b8e1d06a3427",
    "data": {
      "madi_5d8b21c74e0af96b3d15": {
        "type": "input",
        "value": "message",
        "placeholder": "Paste the message",
        "required": true
      }
    },
    "instruction": {
      "miid_9a4c07e5b312df8641ca": {
        "type": "system",
        "instruction": "Classify the message as low, normal or urgent."
      }
    },
    "status": "activated",
    "created_at": 1754205600
  }
}

Note — Creation answers 200, not 201, and its data and instruction are objects keyed by the new identifiers rather than the arrays the read endpoints return. Read the app back with GET /v1/app/detail/<app_id> if you need the standard shape.

At least one field of data must be required, otherwise the call is refused with 422 and At least one data field must be required. An unknown field type gives 404 and The selected data type does not exist., and an unknown instruction type gives 404 and The selected instruction type does not exist.

Data field types

The type you send in data is one of the names below (its identifier is also accepted, and it is the identifier the read endpoints return).

typeIdentifierWhat the field collects
inputmdti_c2a39a7ad82bc017dccdOne line of text.
text areamdti_fdd932b23e1fa82aa942A block of text.
numbermdti_0bf56e96d417b823b7e8A number.
emailmdti_52f84207d0f8a95ed43dAn email address.
documentmdti_5017cf8657e1df4df809A PDF, DOCX, XLSX, CSV or TXT file. The model reads its text.
imagemdti_1777f1beedfbd5cde030A PNG, JPG or WebP image. The model looks at it.

document and image fields do not take typed text: a run supplies a file your project has already uploaded. See Runs for how to send one, and note that an image field only works with a model that reads images.

Creation is also gated on the project's plan. A plan that allows no custom apps, and a project that has reached its app limit, are both refused with 402 — see Error codes.

List your apps

GET /v1/app/list returns the project's own apps, newest first, excluding deleted ones. It accepts limit and offset.

curl
curl "https://api.thinkhx.com/v1/app/list?limit=2" \
  -H "Authorization: Bearer sk-project-YOUR_KEY"
json
{
  "code": 200,
  "title": "OK",
  "response": {
    "object": "list",
    "data": [
      {
        "id": "mapp_0ceacb46e5b3a99e91b6",
        "object": "app",
        "name": "Support triage",
        "description": "Sorts an inbound support message by urgency.",
        "type": "private",
        "status": "activated",
        "model": "modi_7b1e4c2a9d05f3618ea4",
        "model_library": "mlyi_2c9a7f45b8e1d06a3427",
        "runs": { "private": 12, "public": 0 },
        "tokens": { "input": 8420, "output": 3115, "total": 11535 },
        "created_at": 1754205600,
        "updated_at": 1754205600
      }
    ],
    "total": 1
  }
}

The list omits data, instruction and logo. Read one app to get them.

Read one app

GET /v1/app/detail/<app_id> returns the full object, including the input schema you need in order to launch a run.

curl
curl https://api.thinkhx.com/v1/app/detail/mapp_0ceacb46e5b3a99e91b6 \
  -H "Authorization: Bearer sk-project-YOUR_KEY"
json
{
  "code": 200,
  "title": "OK",
  "response": {
    "id": "mapp_0ceacb46e5b3a99e91b6",
    "object": "app",
    "name": "Support triage",
    "description": "Sorts an inbound support message by urgency.",
    "type": "private",
    "status": "activated",
    "logo": "file_d81e4afa6c8bf11fa881",
    "model": "modi_7b1e4c2a9d05f3618ea4",
    "model_library": "mlyi_2c9a7f45b8e1d06a3427",
    "data": [
      {
        "id": "madi_5d8b21c74e0af96b3d15",
        "name": "message",
        "type": "mdti_c2a39a7ad82bc017dccd",
        "placeholder": "Paste the message",
        "required": true
      }
    ],
    "instruction": [
      {
        "id": "miid_9a4c07e5b312df8641ca",
        "type": "system",
        "instruction": "Classify the message as low, normal or urgent."
      }
    ],
    "runs": { "private": 12, "public": 0 },
    "tokens": { "input": 8420, "output": 3115, "total": 11535 },
    "created_at": 1754205600,
    "updated_at": 1754205600
  }
}

You can read your own apps in any status, and any activated public app of any project. Reading someone else's public app hides what belongs to its owner: instruction comes back as null and runs.private as 0, and tokens reports what your own project spent on it rather than the owner's total. Anything else gives 404 and App not found.

Edit an app

PATCH /v1/app/detail/<app_id> changes the name, the description and the visibility. Send at least one of them.

ParameterTypeDescription
namestringA new name. An empty value is refused.
descriptionstringA new description. An empty value is refused.
typestringpublic to publish the app, private to withdraw it.
curl
curl -X PATCH https://api.thinkhx.com/v1/app/detail/mapp_0ceacb46e5b3a99e91b6 \
  -H "Authorization: Bearer sk-project-YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "type": "public" }'
json
{
  "code": 200,
  "title": "OK",
  "response": {
    "id": "mapp_0ceacb46e5b3a99e91b6",
    "object": "app",
    "name": "Support triage",
    "description": "Sorts an inbound support message by urgency.",
    "type": "public",
    "status": "activated",
    "model": "modi_7b1e4c2a9d05f3618ea4",
    "model_library": "mlyi_2c9a7f45b8e1d06a3427",
    "created_at": 1754205600,
    "updated_at": 1754209200
  }
}

Publishing has two conditions. The app must already be activated, otherwise the call is refused with 422 and The app must be activated before it can be published., and it must carry an image logo, otherwise 422 and The app needs an image logo before it can be published. Withdrawing an app always succeeds. A type that is neither value gives 422 and type must be 'public' or 'private'.

Sending nothing recognisable gives 422 and Nothing to update. Provide name, description and/or type.

Delete an app

DELETE /v1/app/detail/<app_id> withdraws the app. It stops appearing in every listing and can no longer be read or run.

curl
curl -X DELETE https://api.thinkhx.com/v1/app/detail/mapp_0ceacb46e5b3a99e91b6 \
  -H "Authorization: Bearer sk-project-YOUR_KEY"
json
{
  "code": 200,
  "title": "OK",
  "response": {
    "deleted": true,
    "id": "mapp_0ceacb46e5b3a99e91b6"
  }
}

Note — The runs the app has already produced are kept and stay readable through Runs.

Need help? Contact Support.