> ## Documentation Index
> Fetch the complete documentation index at: https://docs.neuro-tech.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Author a token with a state machine and Script

> Define a complete token creation contract, submit it through the Agent API, and check its first owner-note transition

Build a token definition whose first owner text note increments a stored counter and ends the machine. The contract, machine, and embedded expression are supplied as complete files.

The XML and core calculation have been tested locally with `Waher.Script` 2.15.0. Token creation and the first transition still need to be tested on your development Neuron.

## Prerequisites

* Complete [contract authoring and submission](/contracts/from-scratch).
* Obtain an approved Creator Legal Identity, its signing key, and access to token and state-machine Agent API operations.
* Confirm the provider supports this token creation vocabulary and the [selected schema set](/resources/schemas).
* Arrange the TrustProvider role, template approval, any creation charge, and the provider's signing procedure. You cannot sign the provider's role with your Creator key.
* Confirm an accepted value, currency, commission percentage, and expiration date. Zero value in the sample request is a placeholder choice, not a guarantee of free creation.

## 1. Start with the complete definition

Save the complete definition below as `note-token.xml`, or [download the XML file](/downloads/examples/note-token.xml).

<Accordion title="Complete token creation contract">
  ```xml theme={null}
  <?xml version="1.0" encoding="utf-8"?>
  <contract xmlns="urn:nf:iot:leg:sc:1.0"
            canActAsTemplate="true" visibility="CreatorAndParts"
            duration="P1M" archiveReq="P1M" archiveOpt="P1M">
    <Create xmlns="https://paiwise.tagroot.io/Schema/NeuroFeatures.xsd">
      <TokenID><Random /></TokenID>
      <Creator><RoleReference role="Creator" /></Creator>
      <Owner><RoleReference role="Creator" /></Owner>
      <TrustProvider><RoleReference role="TrustProvider" /></TrustProvider>
      <Value><ParameterReference parameter="Value" /></Value>
      <Currency><ParameterReference parameter="Currency" /></Currency>
      <CommissionPercent><ParameterReference parameter="CommissionPercent" /></CommissionPercent>
      <Expires><ParameterReference parameter="Expires" /></Expires>
      <Definition>
        <StateMachine xmlns="https://paiwise.tagroot.io/Schema/StateMachines.xsd" startState="Waiting">
          <Variable id="Count"><Number>0</Number></Variable>
          <State id="Waiting">
            <OnEvent actionRef="RecordNote" newState="Complete" failureState="Failed">
              <OnTextNote />
            </OnEvent>
          </State>
          <State id="Complete"><OnEnter actionRef="Stop" /></State>
          <State id="Failed"><OnEnter actionRef="Stop" /></State>
          <Action id="RecordNote">
            <Script>NextCount:=Count+1</Script>
            <PersistVariable name="Count" value="{NextCount}" onlyIfChanged="true" />
          </Action>
          <Action id="Stop"><End /></Action>
        </StateMachine>
      </Definition>
      <FriendlyName><ParameterReference parameter="FriendlyName" /></FriendlyName>
      <Category><String>Documentation example</String></Category>
      <Description><String>Records the first owner text note as a single completed step.</String></Description>
      <Glyph contentType="image/png">iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR4nGNQbnr4HwAE2AKGjcL8KQAAAABJRU5ErkJggg==</Glyph>
    </Create>
    <role name="Creator" minCount="1" maxCount="1">
      <description xml:lang="en"><paragraph><text>Creates and initially owns the token.</text></paragraph></description>
    </role>
    <role name="TrustProvider" minCount="1" maxCount="1">
      <description xml:lang="en"><paragraph><text>Approves and hosts token creation under its service rules.</text></paragraph></description>
    </role>
    <parts><templateOnly /></parts>
    <parameters>
      <numericalParameter name="Value" min="0" minIncluded="true">
        <description xml:lang="en"><paragraph><text>Initial value accepted by the provider.</text></paragraph></description>
      </numericalParameter>
      <stringParameter name="Currency" minLength="1">
        <description xml:lang="en"><paragraph><text>Currency or value unit accepted by the provider.</text></paragraph></description>
      </stringParameter>
      <numericalParameter name="CommissionPercent" min="0" minIncluded="true">
        <description xml:lang="en"><paragraph><text>The provider's required creation commission percentage.</text></paragraph></description>
      </numericalParameter>
      <dateTimeParameter name="Expires">
        <description xml:lang="en"><paragraph><text>Token expiration within the creation contract's valid period.</text></paragraph></description>
      </dateTimeParameter>
      <stringParameter name="FriendlyName" minLength="1" maxLength="80">
        <description xml:lang="en"><paragraph><text>The display name of the demonstration token.</text></paragraph></description>
      </stringParameter>
    </parameters>
    <humanReadableText xml:lang="en">
      <paragraph><text>The Creator requests one token named </text><parameter name="FriendlyName" /><text> and will be its initial owner. The TrustProvider must approve its creation.</text></paragraph>
      <paragraph><text>The initial value is </text><parameter name="Value" /><text> </text><parameter name="Currency" /><text>. The creation commission is </text><parameter name="CommissionPercent" /><text> percent. The token expires at </text><parameter name="Expires" /><text>.</text></paragraph>
      <paragraph><text>The machine starts in Waiting with Count equal to zero. The first owner text note runs a calculation and persists Count as one, then enters Complete and ends. If the action fails, it enters Failed and ends. Later notes do not repeat this machine step. No external-note event or payment action is defined by the machine.</text></paragraph>
      <paragraph><text>The creation contract lasts one month, followed by one month of required archival and one month of optional archival. Provider rules and approval apply; this demonstration has not been verified on your service.</text></paragraph>
    </humanReadableText>
  </contract>
  ```
</Accordion>

Three namespaces separate the contract, token creation instruction, and machine definition. Keep them exactly as supplied.

| Contract section                                    | Meaning                                                                                  |
| --------------------------------------------------- | ---------------------------------------------------------------------------------------- |
| `Create/TokenID/Random`                             | Request a generated token identifier. Do not confuse it with the creation contract ID.   |
| `Creator` and `Owner`                               | Both refer to the `Creator` role for this example.                                       |
| `TrustProvider`                                     | Refers to the provider's Legal Identity assigned to that role.                           |
| `Value`, `Currency`, `CommissionPercent`, `Expires` | Read the matching contract parameters.                                                   |
| `Definition/StateMachine`                           | Define the token's custom automated behavior.                                            |
| `FriendlyName`, `Category`, `Description`, `Glyph`  | Supply display metadata. The included glyph is a minimal one-pixel PNG.                  |
| Roles and human-readable text                       | Explain the parties, value, commission, expiration, and machine behavior before signing. |

## 2. Understand the transition

```mermaid theme={null}
stateDiagram-v2
  [*] --> Waiting
  Waiting --> Complete: Owner text note; action succeeds
  Waiting --> Failed: Owner text note; action fails
  Complete --> [*]: End
  Failed --> [*]: End
```

The machine initializes `Count` to zero. In `Waiting`, `OnTextNote` invokes `RecordNote`. A successful action enters `Complete`; a failed action enters `Failed`. Both states invoke `End`.

```xml theme={null}
<Action id="RecordNote">
  <Script>NextCount:=Count+1</Script>
  <PersistVariable name="Count" value="{NextCount}" onlyIfChanged="true" />
</Action>
```

This is a fragment inside the machine namespace. `Script` contains raw Neuron Script. The `value` attribute uses braces to evaluate an expression. `NextCount` is a calculation variable; `PersistVariable` records `Count` for subsequent machine state. An ordinary assignment alone does not replace that persistence step.

The expected successful result is `Count = 1`. Later notes should not repeat this ended machine's step. This is a design expectation to verify on your provider, not a general duplicate-event guarantee.

Read [Script syntax and execution contexts](/script/runtime-functions) when changing the calculation. If you add a less-than comparison in an XML attribute, escape it as `&lt;`.

## 3. Validate before proposing

Validate the complete file against the [contract, token, and state-machine schemas](/resources/schemas), following [local validation](/resources/validate-xml). Check that each state and action reference names a definition in the same machine.

Expected result: the schema set compiles, the XML validates, and all explicit machine references resolve. The core expression `Count:=0; NextCount:=Count+1; NextCount` returns `1`; see [Script expressions](/script/quickstart).

Neither check approves the template or runs the machine in its host context.

## 4. Obtain creation attributes and template approval

Send the following requests over HTTPS with your account’s exact host, JWT, and application URL as `Referer`. Replace every placeholder before sending a request.

```http theme={null}
POST /Agent/Tokens/GetCreationAttributes HTTP/1.1
Host: <NEURON_HOST>
Referer: https://your-app.example/
Authorization: Bearer <JWT>
Accept: application/json
Content-Type: application/json

{}
```

[Get Creation Attributes](/neuron-api/api-reference/tokens/get-creation-attributes) returns `currency`, `commission`, and `trustProvider`. A missing provider identity is a provisioning issue to resolve before creation. Confirm how these values apply to the accepted template and charges.

Base64-encode the complete `note-token.xml` file’s UTF-8 bytes and propose it:

```http theme={null}
POST /Agent/Legal/ProposeTemplate HTTP/1.1
Host: <NEURON_HOST>
Referer: https://your-app.example/
Authorization: Bearer <JWT>
Accept: application/json
Content-Type: application/json

{
  "templateBase64": "<BASE64_OF_COMPLETE_UTF8_XML>"
}
```

Record the returned `Template` identifier and follow the [sandbox automatic review or operator approval process](/build/agreements/overview#contract-approval). Use `Legal/GetContract` with that identifier as `contractId` to observe the template lifecycle. Continue only with an approved, usable template. Template approval does not supply the `TrustProvider` signature required by this creation contract.

## 5. Create and sign the creation contract

Prepare the creation request:

* Set the approved template ID.
* Assign `Creator` to your approved Legal Identity and `TrustProvider` to the provider's approved identity.
* Set `Value` and `CommissionPercent` as JSON numbers. Replace the quoted commission placeholder with an actual number.
* Set `Currency` to the accepted string and `Expires` to an ISO 8601 date-time accepted by the provider within the creation contract's valid period.
* Choose `FriendlyName`, from 1 to 80 characters.

```http theme={null}
POST /Agent/Legal/CreateContract HTTP/1.1
Host: <NEURON_HOST>
Referer: https://your-app.example/
Authorization: Bearer <JWT>
Accept: application/json
Content-Type: application/json

{
  "templateId": "<APPROVED_NOTE_TOKEN_TEMPLATE_ID>",
  "visibility": "CreatorAndParts",
  "Parts": [
    { "role": "Creator", "legalId": "<CREATOR_LEGAL_ID>" },
    { "role": "TrustProvider", "legalId": "<TRUST_PROVIDER_LEGAL_ID>" }
  ],
  "Parameters": [
    { "name": "Value", "value": 0 },
    { "name": "Currency", "value": "<PROVIDER_CURRENCY>" },
    { "name": "CommissionPercent", "value": "<PROVIDER_COMMISSION_AS_JSON_NUMBER>" },
    { "name": "Expires", "value": "<ISO_8601_EXPIRATION_ACCEPTED_BY_PROVIDER>" },
    { "name": "FriendlyName", "value": "My first note token" }
  ]
}
```

Record the returned `Contract` ID. Retrieve the instance:

```http theme={null}
POST /Agent/Legal/GetContract HTTP/1.1
Host: <NEURON_HOST>
Referer: https://your-app.example/
Authorization: Bearer <JWT>
Accept: application/json
Content-Type: application/json

{
  "contractId": "<CONTRACT_ID>"
}
```

Have the Creator review the complete terms, parameters, and assigned role. After confirmation, calculate the [contract signatures](/neuron-api/guides/contracts-flow#construct-a-contract-signature) using the Creator’s key metadata, key password, account password, and a fresh nonce. Submit:

```http theme={null}
POST /Agent/Legal/SignContract HTTP/1.1
Host: <NEURON_HOST>
Referer: https://your-app.example/
Authorization: Bearer <JWT>
Accept: application/json
Content-Type: application/json

{
  "keyId": "<SIGNER_KEY_ID>",
  "legalId": "<SIGNER_LEGAL_ID>",
  "contractId": "<REVIEWED_CONTRACT_ID>",
  "role": "Creator",
  "nonce": "<FRESH_NONCE>",
  "keySignature": "<CALCULATED_KEY_SIGNATURE>",
  "requestSignature": "<CALCULATED_REQUEST_SIGNATURE>"
}
```

Retrieve the instance again with `Legal/GetContract` and the same contract ID. Coordinate the provider's required signature separately. Observe all required signatures and the creation contract's final state. Do not assume your first signature creates the token.

## 6. Find the created token

Retrieve tokens associated with the creation contract:

```http theme={null}
POST /Agent/Tokens/GetContractTokens HTTP/1.1
Host: <NEURON_HOST>
Referer: https://your-app.example/
Authorization: Bearer <JWT>
Accept: application/json
Content-Type: application/json

{
  "contractId": "<CREATION_CONTRACT_ID>",
  "offset": 0,
  "maxCount": 20,
  "references": true
}
```

Inspect the returned `Tokens` structure for the token associated with this creation contract. Preserve the exact identifier. An empty list can mean creation is pending or failed; inspect the contract and provider result before submitting another creation request.

Use the returned token identifier to retrieve the token and machine state:

```http theme={null}
POST /Agent/Tokens/GetToken HTTP/1.1
Host: <NEURON_HOST>
Referer: https://your-app.example/
Authorization: Bearer <JWT>
Accept: application/json
Content-Type: application/json

{
  "tokenId": "<TOKEN_ID>"
}
```

```http theme={null}
POST /Agent/StateMachines/GetCurrentState HTTP/1.1
Host: <NEURON_HOST>
Referer: https://your-app.example/
Authorization: Bearer <JWT>
Accept: application/json
Content-Type: application/json

{
  "tokenId": "<TOKEN_ID>"
}
```

Verify the token's owner, creation contract, metadata, and current machine state. The expected starting machine state is `Waiting` with `Count = 0`. The state response contains `CurrentState`; use its returned structure rather than assuming an invented flat `state` field.

## 7. Send an owner note and observe the result

Send this request with the account that owns the token, using the same token ID. The request sets `personal` to `false`.

```http theme={null}
POST /Agent/Tokens/AddTextNote HTTP/1.1
Host: <NEURON_HOST>
Referer: https://your-app.example/
Authorization: Bearer <JWT>
Accept: application/json
Content-Type: application/json

{
  "tokenId": "<TOKEN_ID>",
  "note": "First owner note",
  "personal": false
}
```

Repeat `StateMachines/GetCurrentState` above, and retrieve the event history:

```http theme={null}
POST /Agent/Tokens/GetTokenEvents HTTP/1.1
Host: <NEURON_HOST>
Referer: https://your-app.example/
Authorization: Bearer <JWT>
Accept: application/json
Content-Type: application/json

{
  "tokenId": "<TOKEN_ID>"
}
```

The note response contains `Note`. A note being accepted is separate from confirming the intended machine outcome. Retrieve the state and event history until the provider's documented completion window, with bounded polling in your application.

For this example, verify `Complete`, the persisted `Count = 1`, and the corresponding note/action history. Record actual results and the Neuron build before treating the workflow as tested. If you receive `Failed`, preserve the returned diagnostic/history information and resolve the action failure before adapting the template.

## Diagnose and adapt

| Situation                   | What to do                                                                                                                               |
| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| Provider identity is absent | Resolve provider provisioning before assigning roles.                                                                                    |
| No token after signatures   | Inspect contract state and provider execution; do not repeat creation blindly.                                                           |
| Note rejected               | Check token ownership or approved external-source permissions. This example listens for an owner note, not an external note.             |
| State-machine not found     | Verify token ID, creation result, definition, and enabled capability.                                                                    |
| Action fails                | Inspect the reported Script error, variable types, and persistence result. Local core-expression success does not prove host permission. |
| Write times out             | Reconcile notes/events and current state before resending; the operation does not document an idempotency guarantee.                     |

When adapting this example, keep role references, parameter names, state IDs, and action references aligned. Update human-readable terms whenever automated behavior changes, validate the new file, and obtain a newly reviewed template when required by your provider.

Retain the creation contract ID, token ID, template revision, input values, and observed state/history. Ending this custom machine does not itself destroy the token or delete its contract. Follow the asset's supported expiration and retention rules; transfer and destruction require their own approved behavior.
