Skip to main content

Integrations

A connected exchange, wallet or blockchain address, with its sync state and per-asset holdings.

Base URL: https://api-v2.kryptos.io · Required Permission: integrations:read

EndpointReturns
GET/v1/integrationsList, filter, paginate
GET/v1/integrations/{id}One integration, with sync and CSV history
GET/v1/integrations/searchTypeahead search
GET/v1/integrations/sync-statusMost recent sync time
GET/v1/integrations/{id}/assetsPer-asset holdings breakdown

Users connect accounts through the Kryptos Connect widget, which handles credentials, OAuth and CSV upload for you.

List integrations​

curl -X GET "https://api-v2.kryptos.io/v1/integrations?workspaceId=WORKSPACE_ID&page=1&limit=50" \
-H "Authorization: Bearer ACCESS_TOKEN"

Query Parameters​

ParameterTypeDefaultDescription
workspaceIdstring—Required unless your token is workspace-bound
primaryPortfolioIdstring—Scope to one portfolio
providerIdstring—Filter by provider
providerTypestring—exchange, blockchain, wallet, service, aggregator, custom
statusstring—pending, active, inactive, suspended, error
searchstring—Match on alias, address and account name
hasMissingBalanceboolean—Only accounts whose calculated balance disagrees with the provider's
fieldsstring—summary returns a lighter payload, see below
includeProviderCountsbooleanfalseAlso return providerCounts, the per-provider tally for the workspace
sortBystringcreatedAtalias, addedOn, createdAt, updatedAt, lastSyncedAt, netValue, txnCount
sortOrderstringdescasc or desc
pageinteger1Page number
limitinteger501–100, silently clamped

Response​

{
"success": true,
"data": {
"integrations": [
{
"id": "int_9f2c",
"workspaceId": "ws_12ab",
"providerId": "binance",
"primaryPortfolioId": "pf_main",
"alias": "Main exchange",
"accountStatus": "active",
"credentialKind": "api_key",
"syncEnabled": true,
"isCustomWallet": false,
"provider": {
"id": "binance",
"name": "Binance",
"publicName": "Binance",
"logo": "https://...",
"type": "exchange"
},
"lastSyncId": "sync_7712",
"lastSyncedAt": "2026-08-13T09:14:22.000Z",
"latestSync": {
"id": "sync_7712",
"status": "completed",
"syncKind": "api",
"mode": "incremental",
"progressPercent": 100,
"recordsProcessed": 412,
"recordsFailed": 0,
"limitReached": false,
"completedAt": "2026-08-13T09:16:02.000Z"
},
"txnCounts": { "total": 1284, "byType": { "trade": 900, "deposit": 220 } },
"netValue": 150000,
"baseCurrency": "USD",
"metadataUpdatedAt": "2026-08-13T09:16:30.000Z",
"hasMissingBalance": false,
"canResync": true,
"assetLogos": ["https://...", "https://..."],
"assetCount": 12,
"txnCount": 1284,
"credentials": null,
"createdAt": "2026-01-04T11:02:00.000Z",
"updatedAt": "2026-08-13T09:16:30.000Z",
"deletedAt": null
}
],
"pagination": { "page": 1, "limit": 50, "total": 7, "totalPages": 1, "hasMore": false }
}
}

Response Fields​

FieldTypeDescription
idstringIntegration id — the walletId other endpoints refer to
providerIdstringProvider slug. See Providers
primaryPortfolioIdstring | nullPortfolio it belongs to
aliasstring | nullUser-facing name
accountStatusstringpending, active, inactive, suspended, deleting, deleted, error
credentialKindstringapi_key, oauth, address, account_name, wallet_connect, csv, none
syncEnabledbooleanAutomatic syncing is on
isTokenExpiredbooleanAn OAuth credential needs reconnecting
lastSyncStatusstring | nullStatus of the last finished sync; latestSync.status is the live one
isCustomWalletbooleanA manual wallet with no provider connection
lastSyncId, lastSyncedAtstringMost recent sync
latestSyncobject | nullMost recent sync of any status; null if never synced
txnCountsobject | null{ total, byType }; null until first computed
netValuenumber | nullHoldings value in the workspace base currency
metadataUpdatedAtstring | nullWhen txnCounts and netValue were last refreshed
hasMissingBalancebooleanSee below
canResyncbooleanA credential exists to re-sync against, so "Resync" applies
assetLogosarrayUp to 5 asset logos, for list rendering
assetCountnumberDistinct assets held in this account
txnCountnumberConvenience copy of txnCounts.total
credentialsobject | nullConnection identifier for address / account_name kinds, secrets masked; null for secret-bearing kinds
createdAt, updatedAt, deletedAtstringISO 8601 timestamps

Read txnCounts, netValue, baseCurrency and metadataUpdatedAt as the top-level fields above rather than out of the raw metadata bag they are derived from.

Provider counts​

providerCounts — a per-provider tally across the whole workspace — is off by default. It is a separate aggregate over every integration, not a summary of the page you asked for, so it is opt-in: pass ?includeProviderCounts=true and it appears beside pagination.

If the tally is all you need, GET /v1/integrations/counts-by-provider answers it directly without paging the list.

The nested provider​

On the list, provider carries only what a row renders — id, name, publicName, logo and type. The full catalogue entry is not repeated per row: a workspace with ten Ethereum wallets would otherwise receive the same provider ten times.

GET /v1/integrations/{id} returns the complete provider, including importMethods, credentialFields, capabilities, walletLimitations, integrationInfo, metadata and functions. For the whole catalogue in one call, use GET /v1/providers and join on providerId.

txnCounts and netValue come from cached metadata refreshed by the recompute pipeline, so metadataUpdatedAt may lag lastSyncedAt by a few seconds after a sync. Compare the two before presenting the numbers as current. txnCounts.total is not additive across integrations — an internal transfer is counted for both wallets it touches. netValue is additive.

hasMissingBalance is true when any asset's ledger-derived balance differs from the provider-reported one by more than 0.01. It is evaluated live per request, so it always agrees with the hasMissingBalance filter. CSV and manual integrations have no provider-reported balance to compare, so they are false — unverifiable, not verified.

fields=summary​

For menus and pickers, where the full row is wasted bytes. Each entry carries only:

id, alias, providerId, providerName, providerPublicName, logo, transactionCount, address.

pagination is returned as normal. The live per-page lookups the full payload runs — hasMissingBalance, canResync, asset logos and counts — are skipped, which is most of why it is cheaper.

Sync status values​

latestSync.status is one of pending, queued, in_progress, completed, partially_synced, failed, cancelled. The last four are terminal.

partially_synced is a success with losses, not a failure — treating it as one will make users re-run syncs that already imported most of their data. Two different things produce it, and latestSync.limitReached tells them apart:

  • limitReached: true — the workspace hit its transaction limit mid-run. Rows before the cut are saved; the rest were never fetched. The wallet's history is incomplete until the cap is raised and the integration is re-synced from the start — raising the cap alone backfills nothing.
  • limitReached: false — one or more provider functions failed while the others succeeded. Read recordsFailed.

limitReached is the v2 replacement for v1's limitExceeded.

One integration​

GET /v1/integrations/{id} returns the same object as { success, data }, plus two fields the list omits:

FieldTypeDescription
connectionsarrayPer-chain connection rows for a multi-chain wallet
csvUploadsarrayUpload history, newest first: uploadId, fileName, fileSize, fileType, status, rowCount, summary, uploadedAt

It omits the list-only derived fields in exchange — assetLogos, assetCount, txnCount, txnCounts, netValue, hasMissingBalance and metadataUpdatedAt.

Secrets are never returned for api_key, oauth or wallet_connect credentials, on either route.

Per-asset breakdown​

curl -X GET "https://api-v2.kryptos.io/v1/integrations/int_9f2c/assets?workspaceId=WORKSPACE_ID" \
-H "Authorization: Bearer ACCESS_TOKEN"
ParameterTypeDefaultDescription
workspaceIdstring—Required unless your token is workspace-bound
qstring—Match on asset symbol or name, max 100 characters
includeSpambooleanfalseInclude assets flagged as spam
minValuenumber—Drop assets worth less than this
pageinteger1Page number
limitinteger501–100

Returns { success, data: { assets, pagination } } — the per-asset detail behind this integration's netValue.

Helpers​

GET /v1/integrations/search — typeahead. Both workspaceId and q are required; omitting either returns 400. Returns { success, data: { integrations } }.

GET /v1/integrations/sync-status — returns { success, data: { lastSyncedAt } }, the most recent sync across the workspace. It takes only an optional portfolioId; the workspace comes from your token rather than a query parameter.