Skip to content
AXUS IDAXUS ID
Docs/Become an app
On this page

Build & explore / Become an app

Your AUID.
Your permission model.

Every AXUS ID account can own an app context. Publish declarations under your AUID so AXUS ID can validate and describe the access your app supports.

Publish the complete definition.

Open Account → Developer → Permission declarations or call the mutation below. Use your own AUID as ownerAuid; it becomes the declaration context. Publishing requires your system capability identity.<owner>.grants.delegate.

Publish with GraphQL variables
mutation PublishPermission($owner: ID!, $declaration: PermissionDeclarationInput!) {
  publishPermissionDeclaration(ownerAuid: $owner, declaration: $declaration) {
    id context name version template title description icon validatorUrl order
  }
}
Static declaration — pass as declaration
{
  "name": "section.posts.create",
  "template": "section.{section}.posts.create",
  "params": [
    {
      "name": "section",
      "type": "STRING",
      "allowWildcard": true,
      "allowedValues": [
        "news",
        "community"
      ],
      "label": "Section",
      "hint": "Choose the section where posts may be created."
    }
  ],
  "title": "Create posts in {section}",
  "description": "Create posts in the {section} section.",
  "icon": "file-plus",
  "order": 10
}

Every {param} template segment must have a matching entry in params. Empty literals and literal * or ? are reserved. Parameter names must be unique. Publishing the same name updates the existing declaration in place and increments its version. Keep the full definition in your app’s source and submit it again when updating.

Publishing defines valid keys; it does not create permission grants. Arrange initial app-context grants through the engine’s provisioning process, then use delegation for holders to share access.

Types, constraints and display metadata.

TypeBinding
STRINGText in one dot-separated segment
INTEGERSigned 32-bit integer text
LONGSigned 64-bit integer text; keep it as a string
DOUBLENumeric text; exponent notation avoids a dot within a segment
BOOLEANExactly true or false
AUIDAn AUID, including comma-separated nested IDs

ParamDefInput supports name, type (default STRING), allowWildcard (default false), allowedValues: [String!], regex, minLength/maxLength, minNumber/maxNumber, and label, description, icon, hint. Numeric constraints use GraphQL Float. Allowed values remain strings for every type.

The declaration supports title, description, icon, validatorUrl, combinationInvariantJs and order. Lower order numbers appear first in declaration lists and permission pickers; declarations without an order come last, with names breaking ties. Titles and descriptions can interpolate bindings using {param}. The app can also personalize permission and parameter text through the describe protocol. The current publishing input does not expose static per-value metadata maps. The website renders recognized icon names such as key, shield, layers and file-plus, with a default icon for others.

For a range declaration with INTEGER parameters named from and to, a combination invariant can be function(bindings) { return Number(bindings.from) <= Number(bindings.to); }. AXUS ID evaluates it; frontend previews never execute the source. Avoid converting LONG values to JavaScript Number in your own invariants.

Validate large or changing sets in your app.

Use validatorUrl when static allowed values cannot represent the set, such as millions of users. AXUS ID calls the endpoint when granting a permission. It does not call it during permission evaluation.

Dynamic declaration
{
  "name": "identity.videos.edit",
  "template": "identity.{subject}.videos.edit",
  "params": [
    {
      "name": "subject",
      "type": "AUID",
      "allowWildcard": false,
      "label": "Video owner",
      "description": "The account whose videos may be edited.",
      "hint": "Search for an account in this app."
    }
  ],
  "validatorUrl": "https://app.example.com/axus/permission-validator",
  "title": "Edit videos owned by {subject}",
  "description": "Edit this account’s videos in our app.",
  "icon": "layers"
}
Validate: POST to validatorUrl
{
  "action": "validate",
  "declarationId": "DECLARATION_UUID",
  "bindings": {
    "subject": "100000000"
  }
}
Validation responses
{"allowed": true}

{"allowed": false, "reason": "This account cannot edit these videos"}

There is a two-second timeout and one retry. A timeout, unavailable endpoint or rejected verdict fails closed: no grant is created. Allowed verdicts are cached for 60 seconds and denied verdicts for 10 seconds. Make validation side-effect-free so retries are safe.

Personalize permission text for each binding.

When someone previews a concrete permission with describePermission, AXUS ID sends its bindings to the same validatorUrl. Return only the fields you want to personalize. For example, your app can resolve an AUID to @likespro for the permission title and the parameter label.

Describe: POST to validatorUrl
{
  "action": "describe",
  "declarationId": "DECLARATION_UUID",
  "bindings": {
    "subject": "100000000"
  }
}
Describe response
{
  "title": "Edit videos owned by @likespro",
  "description": "Edit @likespro’s videos in our app.",
  "params": {
    "subject": {
      "label": "Video owner @likespro",
      "description": "The account whose videos may be edited."
    }
  }
}

title, description, and each parameter’s label and description are optional. Missing fields use the declaration text, with {param} replaced by the binding. If the endpoint fails or times out, the preview uses that declaration text. This affects display only; grant validation still uses the separate validate action.

Notify AXUS ID when validation data changes.

After changing data that affects verdicts, call notifyValidationChanged(declarationId) to drop cached allow and deny verdicts. This requires the declaration owner’s grants.delegate capability. The developer console also provides a manual Clear validation cache action.

Invalidate cached verdicts
mutation InvalidateValidation($declaration: ID!) {
  notifyValidationChanged(declarationId: $declaration)
}

Invalidation changes future grant validation. It is not grant revocation. Existing grants are evaluated without calling your endpoint; explicitly revoke access when your application needs to remove an existing grant.

Discover, describe and delegate.

Use the permission picker workflow and the GraphQL schema explorer for exact signatures and return types. Your app context must be forwarded with every identity permission check and delegation. OAuth scopes for your app use app:<your AUID>:<permission key>; unprefixed scopes use the AXUS ID system context.

Choose permission behavior when starting OAuth authorization: scope for access the app requires, optional_scope for features the user may decline, and conditional_scope for access required only when the account already holds it. Missing mandatory access stops sign-in with access_denied. Enable features from the approved scopes returned by the token endpoint. See the request and consent walkthrough.