Skip to content

Exchange a plugin secret for a session token

POST
/api/plugins/sessions
curl --request POST \
--url https://example.com/api/plugins/sessions \
--header 'Content-Type: application/json' \
--header 'X-MacroDeck-Plugin-Secret: <X-MacroDeck-Plugin-Secret>' \
--data '{ "requestedVersion": { "minimum": 1, "maximum": 1 }, "capabilities": [ { "kind": "example", "localId": "example", "versionRange": { "minimum": 1, "maximum": 1 }, "displayName": "example" } ], "declaredName": "example", "declaredVersion": "example", "sdk": { "sdkVersion": "example", "deprecatedApis": [ "example" ], "truncated": true } }'

Authenticated by the plugin id and secret headers. Negotiation happens here, once, and is authoritative - the subsequent session.hello over the WebSocket only asserts the outcome, it never re-negotiates.

Media typeapplication/json

Mirrors MacroDeck.Plugin.Protocol.Handshake.PluginSessionRequest.

object
requestedVersion
required

Mirrors MacroDeck.Plugin.Protocol.Versioning.ProtocolVersionRange.

object
minimum
required
integer
maximum
required
integer
capabilities
required
Array<object>

Mirrors MacroDeck.Plugin.Protocol.Handshake.DeclaredCapability.

object
kind
required

One of x-macrodeck-capability-kinds.

string
localId
required
string
versionRange
required

Mirrors MacroDeck.Plugin.Protocol.Versioning.CapabilityVersionRange.

object
minimum
required
integer
maximum
required
integer
displayName
string
declaredName

The plugin’s own display name for this session, as declared by the plugin process itself. Optional and additive - names the current session only, never the plugin’s enrollment record.

string
nullable <= 128 characters
declaredVersion

The plugin’s own version, from its manifest’s “version”. Optional and additive - sent on every session so a self-updating plugin reports its new version without re-enrolling.

string
nullable <= 128 characters
sdk

Mirrors MacroDeck.Plugin.Protocol.Handshake.PluginSdkUsage. What the plugin was built against, and which deprecated APIs it actually uses. Optional and additive - a plugin that omits it still negotiates normally and is reported as compatibility source “unknown”.

object
sdkVersion
required

The version of MacroDeck.Sdk the plugin was compiled against.

string
<= 128 characters
deprecatedApis

Documentation comment ids of the deprecated APIs the plugin references, captured at build time by the SDK’s usage-manifest generator. Null and empty mean different things and must never be conflated - null is “not reported”, so the host can only infer from sdkVersion; empty is “reported, and none are used”, which the host treats as confirmed.

Array<string>
nullable <= 64 items
truncated

True when the generator hit its cap, so the list is a floor rather than the complete set.

boolean
Examplegenerated
{
"requestedVersion": {
"minimum": 1,
"maximum": 1
},
"capabilities": [
{
"kind": "example",
"localId": "example",
"versionRange": {
"minimum": 1,
"maximum": 1
},
"displayName": "example"
}
],
"declaredName": "example",
"declaredVersion": "example",
"sdk": {
"sdkVersion": "example",
"deprecatedApis": [
"example"
],
"truncated": true
}
}

The session was created.

Media typeapplication/json

Mirrors MacroDeck.Plugin.Protocol.Handshake.PluginSessionResponse.

object
sessionId
required
string
sessionToken
required
string
negotiatedVersion
required
integer
capabilities
required
Array<object>

Mirrors MacroDeck.Plugin.Protocol.Versioning.CapabilityNegotiationResult.

object
kind
required
string
accepted
required
boolean
negotiatedVersion
integer
rejectionReason
string
limits
required

Mirrors MacroDeck.Plugin.Protocol.Handshake.PluginProtocolLimitsDescriptor.

object
maxMessageBytes
required
integer
maxAssetBytes
required
integer
maxAssetChunkBytes
required
integer
maxInboundQueueDepth
required
integer
maxOutboundQueueDepth
required
integer
queueHighWatermark
required
integer
queueLowWatermark
required
integer
maxConcurrentInvocations
required
integer
maxDeclaredCapabilities
required
integer
maxIdempotencyKeyLength
required
integer
maxErrorMessageLength
required
integer
maxErrorDetailEntries
required
integer
maxJsonDepth
required
integer
maxSessionsPerPlugin
required
integer
timeouts
required

Mirrors MacroDeck.Plugin.Protocol.Handshake.PluginProtocolTimeoutsDescriptor. Each field is a .NET TimeSpan serialized in its default “c” format (e.g. “00:00:10” for ten seconds).

object
handshake
required
string
defaultRequest
required
string
capabilityInvoke
required
string
assetUpload
required
string
keepAliveInterval
required
string
keepAliveTimeout
required
string
sessionResumeWindow
required
string
gracefulClose
required
string
compatibility

Mirrors MacroDeck.Plugin.Protocol.Compatibility.PluginCompatibilityReport.

object
state
required
string
Allowed values: compatible deprecated_apis update_recommended update_required partially_incompatible incompatible
usageSource
required
string
Allowed values: confirmed negotiated inferred unknown
negotiatedProtocolVersion
required
integer
sdkVersion
string
nullable
usageTruncated
boolean
findings
required
Array<object>
<= 128 items

Mirrors MacroDeck.Plugin.Protocol.Compatibility.CompatibilityFinding.

object
diagnosticId
required

The analyzer id this corresponds to, e.g. MDP5002.

string
source
required

The evidence behind the finding. An “inferred” finding says the plugin may be affected.

string
Allowed values: confirmed negotiated inferred unknown
severity
required
string
Allowed values: info warning error
subject
required

A deprecated API’s display name, a capability kind, or “protocol”.

string
guidance
required
string
deprecatedIn
string
nullable
removedIn
string
nullable
replacement
string
nullable
migrationUrl
string
nullable
Example
{
"compatibility": {
"state": "compatible",
"usageSource": "confirmed",
"findings": [
{
"source": "confirmed",
"severity": "info"
}
]
}
}

The request body does not match the expected shape.

Media typeapplication/json

Mirrors MacroDeck.Plugin.Protocol.Errors.ProtocolError.

object
code
required

One of the codes v1 speaks. Drift anchor - see x-macrodeck-error-codes above.

string
Allowed values: PROTOCOL_VERSION_UNSUPPORTED UNKNOWN_MESSAGE_TYPE MALFORMED_ENVELOPE INVALID_PAYLOAD UNAUTHENTICATED PLUGIN_ALREADY_REGISTERED SESSION_EXPIRED SESSION_NOT_RESUMABLE SESSION_REPLACED SESSION_NOT_FOUND CAPABILITY_UNSUPPORTED CAPABILITY_UNAVAILABLE PAYLOAD_TOO_LARGE ASSET_TOO_LARGE QUEUE_OVERFLOW RATE_LIMITED TIMEOUT CANCELLED CORRELATION_UNKNOWN DUPLICATE_IDEMPOTENCY_KEY INTERNAL_ERROR
message
required

Default English text keyed by code (MacroDeck.Plugin.Protocol.Errors.ProtocolErrorMessages). The UI localises from the code, not this string.

string
details
object
key
additional properties
string
retryable
required
boolean
Example
{
"code": "PROTOCOL_VERSION_UNSUPPORTED"
}

Authentication failed. An unknown id and a wrong secret are indistinguishable in the response, the same oracle argument as device login.

Media typeapplication/json

Mirrors MacroDeck.Plugin.Protocol.Errors.ProtocolError.

object
code
required

One of the codes v1 speaks. Drift anchor - see x-macrodeck-error-codes above.

string
Allowed values: PROTOCOL_VERSION_UNSUPPORTED UNKNOWN_MESSAGE_TYPE MALFORMED_ENVELOPE INVALID_PAYLOAD UNAUTHENTICATED PLUGIN_ALREADY_REGISTERED SESSION_EXPIRED SESSION_NOT_RESUMABLE SESSION_REPLACED SESSION_NOT_FOUND CAPABILITY_UNSUPPORTED CAPABILITY_UNAVAILABLE PAYLOAD_TOO_LARGE ASSET_TOO_LARGE QUEUE_OVERFLOW RATE_LIMITED TIMEOUT CANCELLED CORRELATION_UNKNOWN DUPLICATE_IDEMPOTENCY_KEY INTERNAL_ERROR
message
required

Default English text keyed by code (MacroDeck.Plugin.Protocol.Errors.ProtocolErrorMessages). The UI localises from the code, not this string.

string
details
object
key
additional properties
string
retryable
required
boolean
Example
{
"code": "PROTOCOL_VERSION_UNSUPPORTED"
}

The caller did not arrive on a loopback remote address. Plugin endpoints are served on both the public and private listeners, but only local processes may reach them. On the pairing endpoints, on POST /api/plugins/registration, and on POST /api/plugins/sessions for a plugin holding a development credential, this status also means Developer Mode is switched off in the desktop app - such a refusal carries “reason”: “developer_mode_disabled” in the error’s details, and GET /api/plugins/protocol reports the switch ahead of time.

Media typeapplication/json

Mirrors MacroDeck.Plugin.Protocol.Errors.ProtocolError.

object
code
required

One of the codes v1 speaks. Drift anchor - see x-macrodeck-error-codes above.

string
Allowed values: PROTOCOL_VERSION_UNSUPPORTED UNKNOWN_MESSAGE_TYPE MALFORMED_ENVELOPE INVALID_PAYLOAD UNAUTHENTICATED PLUGIN_ALREADY_REGISTERED SESSION_EXPIRED SESSION_NOT_RESUMABLE SESSION_REPLACED SESSION_NOT_FOUND CAPABILITY_UNSUPPORTED CAPABILITY_UNAVAILABLE PAYLOAD_TOO_LARGE ASSET_TOO_LARGE QUEUE_OVERFLOW RATE_LIMITED TIMEOUT CANCELLED CORRELATION_UNKNOWN DUPLICATE_IDEMPOTENCY_KEY INTERNAL_ERROR
message
required

Default English text keyed by code (MacroDeck.Plugin.Protocol.Errors.ProtocolErrorMessages). The UI localises from the code, not this string.

string
details
object
key
additional properties
string
retryable
required
boolean
Example
{
"code": "PROTOCOL_VERSION_UNSUPPORTED"
}

The requested protocol version is not supported.

Media typeapplication/json

Mirrors MacroDeck.Plugin.Protocol.Errors.ProtocolError.

object
code
required

One of the codes v1 speaks. Drift anchor - see x-macrodeck-error-codes above.

string
Allowed values: PROTOCOL_VERSION_UNSUPPORTED UNKNOWN_MESSAGE_TYPE MALFORMED_ENVELOPE INVALID_PAYLOAD UNAUTHENTICATED PLUGIN_ALREADY_REGISTERED SESSION_EXPIRED SESSION_NOT_RESUMABLE SESSION_REPLACED SESSION_NOT_FOUND CAPABILITY_UNSUPPORTED CAPABILITY_UNAVAILABLE PAYLOAD_TOO_LARGE ASSET_TOO_LARGE QUEUE_OVERFLOW RATE_LIMITED TIMEOUT CANCELLED CORRELATION_UNKNOWN DUPLICATE_IDEMPOTENCY_KEY INTERNAL_ERROR
message
required

Default English text keyed by code (MacroDeck.Plugin.Protocol.Errors.ProtocolErrorMessages). The UI localises from the code, not this string.

string
details
object
key
additional properties
string
retryable
required
boolean
Example
{
"code": "PROTOCOL_VERSION_UNSUPPORTED"
}

Too many requests.

Media typeapplication/json

Mirrors MacroDeck.Plugin.Protocol.Errors.ProtocolError.

object
code
required

One of the codes v1 speaks. Drift anchor - see x-macrodeck-error-codes above.

string
Allowed values: PROTOCOL_VERSION_UNSUPPORTED UNKNOWN_MESSAGE_TYPE MALFORMED_ENVELOPE INVALID_PAYLOAD UNAUTHENTICATED PLUGIN_ALREADY_REGISTERED SESSION_EXPIRED SESSION_NOT_RESUMABLE SESSION_REPLACED SESSION_NOT_FOUND CAPABILITY_UNSUPPORTED CAPABILITY_UNAVAILABLE PAYLOAD_TOO_LARGE ASSET_TOO_LARGE QUEUE_OVERFLOW RATE_LIMITED TIMEOUT CANCELLED CORRELATION_UNKNOWN DUPLICATE_IDEMPOTENCY_KEY INTERNAL_ERROR
message
required

Default English text keyed by code (MacroDeck.Plugin.Protocol.Errors.ProtocolErrorMessages). The UI localises from the code, not this string.

string
details
object
key
additional properties
string
retryable
required
boolean
Example
{
"code": "PROTOCOL_VERSION_UNSUPPORTED"
}
Retry-After
required
integer format: int32