Claude-skill-registry imis-api

iMIS API integration patterns and workflows. Use when implementing iMIS API features, adding new endpoints, creating schemas, or debugging API issues. Triggers on: iMIS, ImisApiService, iMIS API, API endpoint, iMIS schema.

install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/imis-api" ~/.claude/skills/majiayu000-claude-skill-registry-imis-api && rm -rf "$T"
manifest: skills/data/imis-api/SKILL.md
source content

iMIS API Development Guide

Reference Code

Do NOT rely on web searches for iMIS API information. Instead, use the reference implementation:

~/.local/share/imis/index.ts

This file contains working API call patterns for many iMIS endpoints. Search it for the endpoint you need:

grep -n "api.party\|api.query\|api.document" ~/.local/share/imis/index.ts

Important: The reference code shows correct request shapes and URL patterns, but may need refactoring to use Effect patterns. Don't copy verbatim—adapt to this project's Effect-based architecture.

API Discovery Workflow

When implementing a new iMIS API endpoint:

Step 1: Find the Pattern

Search the reference code for similar functionality:

grep -A 20 "relevant-endpoint-name" ~/.local/share/imis/index.ts

Step 2: Create Exploration Script

Create a script to hit the real API and inspect the response. This is critical because iMIS response schemas are complex and often inconsistent.

Template (

test/scripts/explore-{endpoint}.ts
):

import { Effect } from "effect"

// Get credentials from environment
const baseUrl = process.env.IMIS_BASE_URL!
const username = process.env.IMIS_USERNAME!
const password = process.env.IMIS_PASSWORD!

// Get token
const tokenResponse = await fetch(`${baseUrl}/token`, {
  method: "POST",
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
  body: `grant_type=password&username=${encodeURIComponent(username)}&password=${encodeURIComponent(password)}`,
})
const { access_token } = await tokenResponse.json()

// Make API request
const response = await fetch(`${baseUrl}/api/{endpoint}`, {
  headers: {
    Authorization: `Bearer ${access_token}`,
    Accept: "application/json",
  },
})
const data = await response.json()

// Pretty print for schema analysis
console.log(JSON.stringify(data, null, 2))

Run with:

bun test/scripts/explore-{endpoint}.ts

Step 3: Analyze Response Shape

Look for:

  • $type
    fields indicating .NET SOA contract types
  • $values
    arrays (iMIS collection pattern)
  • { $type: "System.XXX", $value: ... }
    wrapped primitives
  • Nested
    Properties
    arrays with
    GenericPropertyData

Step 4: Implement

  1. Add schema to
    src/api/imis-schemas.ts
  2. Add method to
    ImisApiService
    in
    src/services/imis-api.ts
  3. Add RPC handler if needed in
    src/api/handlers.ts

Implementation Patterns

Adding a Schema

Follow existing patterns in

src/api/imis-schemas.ts
:

// For simple response types
export const MyResponseSchema = Schema.Struct({
  $type: Schema.String,
  SomeField: Schema.String,
  Items: Schema.Struct({
    $type: Schema.String,
    $values: Schema.Array(MyItemSchema),
  }),
})

// For wrapped values (common in iMIS)
export const WrappedValue = Schema.Struct({
  $type: Schema.String,
  $value: Schema.Unknown,
})

Adding an ImisApiService Method

Use the

executeWithAuth
pattern:

myMethod: (envId: string, param: string) =>
  executeWithAuth(envId, `/api/MyEndpoint`, (token, env) =>
    HttpClientRequest.get(`${env.baseUrl}/api/MyEndpoint`)
      .pipe(
        HttpClientRequest.setUrlParam("param", param),
        HttpClientRequest.bearerToken(token),
        HttpClientRequest.setHeader("Accept", "application/json"),
        httpClient.execute,
        Effect.flatMap(HttpClientResponse.schemaBodyJson(MyResponseSchema)),
        Effect.scoped,
        Effect.withSpan("imis.myMethod", {
          attributes: { environmentId: envId, param },
        })
      )
  ),

For POST requests with

_execute
pattern:

myExecuteMethod: (envId: string, operation: string, params: Record<string, unknown>) =>
  executeWithAuth(envId, `/api/MyEndpoint/_execute`, (token, env) =>
    HttpClientRequest.post(`${env.baseUrl}/api/MyEndpoint/_execute`)
      .pipe(
        HttpClientRequest.bearerToken(token),
        HttpClientRequest.setHeader("Content-Type", "application/json"),
        HttpClientRequest.jsonBody({
          $type: "Asi.Soa.Core.DataContracts.GenericExecuteRequest, Asi.Contracts",
          OperationName: operation,
          EntityTypeName: "MyEndpoint",
          Parameters: {
            $type: "System.Collections.Generic.Dictionary`2[[System.String],[System.Object]], mscorlib",
            ...params,
          },
        }),
        httpClient.execute,
        Effect.flatMap(HttpClientResponse.schemaBodyJson(MyExecuteResponseSchema)),
        Effect.scoped,
        Effect.withSpan("imis.myExecuteMethod", { attributes: { environmentId: envId, operation } })
      )
  ),

Key Files

FilePurpose
src/services/imis-api.ts
ImisApiService - all API methods
src/api/imis-schemas.ts
Request/response schemas
src/api/handlers.ts
RPC handlers using the API
src/api/procedures.ts
RPC procedure definitions
test/imis-api/setup.ts
Test environment setup patterns
~/.local/share/imis/index.ts
Reference API patterns

Common iMIS Patterns

Pagination

  • Max 500 records per request
  • Use
    limit
    and
    offset
    query params
  • Response includes:
    Count
    ,
    TotalCount
    ,
    HasNext
    ,
    NextOffset

Version Differences (EMS vs 2017)

  • EMS uses
    /api/query
    , 2017 uses
    /api/iqa
  • 2017 responses need normalization (see
    normalize2017Response
    )
  • Check
    env.version
    to determine which endpoint

GenericPropertyData

Convert to/from flat objects:

// To properties array (for requests)
const properties = Object.entries(data).map(([Name, Value]) => ({ Name, Value }))

// From properties array (for responses)
const flat = Object.fromEntries(props.map((p) => [p.Name, unwrapValue(p.Value)]))

Error Types

  • ImisAuthError
    - Authentication failed
  • ImisRequestError
    - Network/connection error
  • ImisResponseError
    - HTTP error (includes status code)
  • ImisSchemaError
    - Response parsing failed

Testing

Integration tests use the pattern from

test/imis-api/
:

describe.skipIf(!shouldRunIntegrationTests())("My Feature", () => {
  let envId: string

  beforeAll(async () => {
    envId = await createTestEnvironment()
  })

  afterAll(async () => {
    await cleanupTestEnvironment(envId)
  })

  it("should do something", async () => {
    const result = await runExpectSuccess(ImisApiService.myMethod(envId, "param"))
    expect(result).toBeDefined()
  })
})

Run integration tests:

bun test test/imis-api --timeout 30000