{
  "format": "siebly-integration-kit/v1",
  "id": "bybit-position-manager",
  "title": "Bybit Manual Position Manager Integration Kit",
  "lastReviewed": "2026-05-01",
  "package": {
    "ecosystem": "npm",
    "name": "bybit-api",
    "install": "npm install bybit-api",
    "versionPolicy": "Use the latest available bybit-api package in the generated project. Record the installed version for source verification only.",
    "docs": "https://siebly.io/sdk/bybit/typescript",
    "repository": "https://github.com/tiagosiebler/bybit-api"
  },
  "agentImplementationManifest": "https://siebly.io/.well-known/agent-manifests/bybit-position-manager/latest.json",
  "conformancePack": "https://siebly.io/.well-known/conformance/bybit-position-manager/latest.json",
  "criticalPath": [
    "Install the latest available bybit-api package and record the installed version as source-verification metadata only.",
    "Verify RestClientV5, WebsocketClient, subscribeV5(...), private order/execution/position/wallet topics, lifecycle events, closeAll(true), and REST method names from installed declarations before coding.",
    "Start with read-only REST hydration and dry-run DCA/TP/SL intents. Live order placement, amend, and cancel remain disabled until explicit demo or live gates are enabled and reviewed.",
    "Hydrate instruments, account mode, wallet, positions, active orders, recent orders, executions, and risk limits before planning.",
    "Connect private account-level WebSockets only after scope and credentials are explicit. Buffer private events until REST hydration and replay are complete.",
    "Serialize each category/symbol/positionIdx product workflow so reconciliation, replay, planning, and submission cannot overlap.",
    "Classify every REST order, amend, cancel, and pre-check response by retCode === 0 unless throwExceptions is intentionally enabled.",
    "Use deterministic orderLinkId values for app-owned DCA, TP, SL, replacement, cancel, and amend lifecycles. Preflight duplicate, recent, and in-flight IDs before the first exchange call.",
    "For linear conditional SL orders, include triggerDirection, triggerBy, orderFilter=StopOrder, reduceOnly, closeOnTrigger, and positionIdx after verifying current request types.",
    "Normalize hydrated Bybit active-order defaults before desired-vs-active comparison so accepted app-owned orders converge to intentCount=0 instead of cancel/recreate churn.",
    "Use demoTrading=true and testnet=false as the default exchange execution environment when demo order placement is requested. Do not use Bybit WebSocket API order commands for demo trading."
  ],
  "criticalLiveConformance": {
    "mustPassBeforeLive": [
      "bybit_manual_open_reacts_without_timer",
      "bybit_retcode_nonzero_aborts_batch",
      "bybit_conditional_sl_requires_trigger_direction",
      "bybit_hydrated_defaults_do_not_churn",
      "bybit_duplicate_order_link_id_preflights_batch",
      "bybit_accepted_submissions_settle_to_zero_intents",
      "bybit_deferred_replan_owner_only",
      "bybit_private_stream_exception_prevents_service_ready"
    ],
    "conformancePack": "https://siebly.io/.well-known/conformance/bybit-position-manager/latest.json",
    "requiredOutcome": "Generated projects should create local tests from the conformance pack and keep demo/live submission disabled until these cases pass."
  },
  "sourceVerificationChecklist": [
    "Install the latest available bybit-api package and record the installed version as metadata only.",
    "Run or create the source-verification script before editing exchange code.",
    "Inspect SDK docs, endpoint map, examples, installed TypeScript declarations, and package source for exact methods, request fields, response shapes, lifecycle events, and shutdown methods.",
    "Write SOURCE_VERIFICATION.md with exact methods, types, files, examples, and package version checked."
  ],
  "sourceVerificationScriptShape": {
    "filename": "scripts/verify-bybit-position-manager-surfaces.mjs",
    "command": "node scripts/verify-bybit-position-manager-surfaces.mjs",
    "scriptLines": [
      "import { createRequire } from 'node:module';",
      "const require = createRequire(import.meta.url);",
      "const pkg = require('bybit-api/package.json');",
      "const bybit = await import('bybit-api');",
      "const requiredExports = ['RestClientV5', 'WebsocketClient'];",
      "const report = {",
      "  package: 'bybit-api',",
      "  installedVersion: pkg.version,",
      "  exports: Object.fromEntries(requiredExports.map((name) => [name, Boolean(bybit[name])])),",
      "  manualInspectionTargets: ['submitOrder', 'cancelOrder', 'amendOrder', 'preCheckOrder', 'getInstrumentsInfo', 'getPositionInfo', 'getActiveOrders', 'getHistoricOrders', 'getExecutionList', 'getWalletBalance', 'getAccountInfo', 'getRiskLimit', 'subscribeV5', 'closeAll', 'orderLinkId', 'positionIdx', 'triggerDirection', 'closeOnTrigger', 'orderFilter', 'retCode'],",
      "};",
      "console.log(JSON.stringify(report, null, 2));",
      "if (!report.exports.RestClientV5 || !report.exports.WebsocketClient) process.exitCode = 1;"
    ],
    "reportMustInclude": [
      "installed bybit-api version",
      "RestClientV5 and WebsocketClient export availability",
      "declaration targets inspected before coding",
      "private topic subscription shape",
      "REST method names and response retCode shape",
      "closeAll signature"
    ]
  },
  "canonicalSources": [
    "https://siebly.io/.well-known/agent-manifests/bybit-position-manager/latest.json",
    "https://siebly.io/.well-known/conformance/bybit-position-manager/latest.json",
    "https://siebly.io/ai/position-manager/bybit",
    "https://siebly.io/.well-known/recipes/bybit-position-manager.json",
    "https://siebly.io/sdk/bybit/typescript",
    "https://siebly.io/sdk/bybit/javascript/tutorial",
    "https://siebly.io/llms-tasks.txt",
    "https://siebly.io/.well-known/siebly-sdk-catalog.json",
    "https://github.com/tiagosiebler/bybit-api",
    "https://github.com/sieblyio/crypto-api-examples/tree/master/examples/Bybit"
  ],
  "sdkSurface": {
    "restClient": "RestClientV5",
    "websocketClient": "WebsocketClient",
    "privateSubscribe": "subscribeV5(['order', 'execution', 'position', 'wallet'], 'private') or current equivalent",
    "websocketEvents": [
      "open",
      "response",
      "update",
      "reconnect",
      "reconnected",
      "exception"
    ],
    "shutdown": "closeAll(true) or current documented closeAll variant",
    "rest": [
      "getInstrumentsInfo",
      "getPositionInfo",
      "getActiveOrders",
      "getHistoricOrders",
      "getExecutionList",
      "getWalletBalance",
      "getAccountInfo",
      "getRiskLimit",
      "submitOrder",
      "cancelOrder",
      "amendOrder",
      "preCheckOrder"
    ],
    "customClientIdField": "orderLinkId",
    "positionIdentityField": "positionIdx"
  },
  "requestFieldMatrix": [
    {
      "role": "DCA limit add",
      "category": "linear",
      "fields": "category, symbol, side, orderType=Limit, qty, price, timeInForce, positionIdx, orderLinkId",
      "normalizeAgainstHydration": "Ignore trigger-only fields, closeOnTrigger=false, reduceOnly=false defaults, and empty triggerBy/orderFilter when identity, side, qty, and price match."
    },
    {
      "role": "TP limit reduce",
      "category": "linear",
      "fields": "category, symbol, side, orderType=Limit, qty, price, timeInForce, reduceOnly=true, positionIdx, orderLinkId",
      "normalizeAgainstHydration": "Require reduce-only semantics but normalize false-like hydrated fields only after order identity, side, qty, price, lifecycle, and generation match."
    },
    {
      "role": "SL conditional market",
      "category": "linear",
      "fields": "category, symbol, side, orderType=Market, qty or close-size policy, triggerPrice, triggerDirection, triggerBy, orderFilter=StopOrder, reduceOnly=true, closeOnTrigger=true, positionIdx, orderLinkId",
      "normalizeAgainstHydration": "Compare triggerPrice, triggerDirection, triggerBy, orderFilter, closeOnTrigger, reduceOnly, positionIdx, side, lifecycle, and generation before suppressing replacement."
    },
    {
      "role": "Spot TP/DCA",
      "category": "spot",
      "fields": "category, symbol, side, orderType, qty, price when applicable, timeInForce, orderLinkId",
      "normalizeAgainstHydration": "No derivatives-only positionIdx, reduceOnly, or closeOnTrigger assumptions unless current Bybit docs support them for the selected spot order filter."
    }
  ],
  "eventReconciliationPolicy": [
    "Private order, execution, position, and wallet updates are inputs to the product workflow, not direct planner calls.",
    "Order/execution/position events reconcile immediately when idle; wallet-only clusters may debounce within a bounded window.",
    "Subscription acknowledgement, private update, reconnect, and timer events that arrive during an active workflow record bounded follow-up reasons. The owner workflow schedules one deferred reconcile when it finishes.",
    "Do not recursively append reason strings such as workflow_active_user_data_workflow_active_user_data.",
    "After reconnect or exception, pause demo/live place/amend/cancel, REST hydrate, replay buffered events, and only then resume."
  ],
  "retCodePolicy": {
    "classifier": "const assertBybitOk = (response, context) => {\n  if (response?.retCode === 0) return response.result;\n\n  throw new BybitBusinessError({\n    context,\n    retCode: response?.retCode,\n    retMsg: response?.retMsg,\n    result: response?.result,\n    time: response?.time,\n  });\n};",
    "rules": [
      "retCode === 0 is business acceptance.",
      "retCode !== 0 is rejection or unknown state even when the promise resolved.",
      "Preserve retCode, retMsg, result, time, sanitized request context, category, symbol, positionIdx, role, and orderLinkId in structured logs.",
      "Abort remaining batch items after a non-zero retCode."
    ]
  },
  "commandSafety": [
    "Doctor, inspect, status, readback, and source-verification commands force dry-run/read-only mode.",
    "Demo/live order placement, amend, and cancel require explicit config and acknowledgement.",
    "Unowned manual orders are never canceled or amended by default.",
    "Only app-owned orderLinkId values may be touched by cleanup or replacement logic."
  ],
  "conformanceFixtureNames": [
    "bybit_manual_open_reacts_without_timer",
    "bybit_retcode_nonzero_aborts_batch",
    "bybit_conditional_sl_requires_trigger_direction",
    "bybit_hydrated_defaults_do_not_churn",
    "bybit_duplicate_order_link_id_preflights_batch",
    "bybit_accepted_submissions_settle_to_zero_intents",
    "bybit_deferred_replan_owner_only",
    "bybit_private_stream_exception_prevents_service_ready"
  ]
}
