API Reference
PUT /machine/{key}/monetization
Opt a machine into or out of monetization with a signed request.
PUT
PUT /machine/{key}/monetization
Endpoint
personal_sign), and the machine’s owner or its controller (set in MachineRegistry) may sign. For a Solana-homed machine the signature is Ed25519, and only the owner recorded on the machine account may sign. No on-chain transaction is made.
Opting in requires the machine to be , and a peaq-homed machine must also be available (not deactivated or paused). Opting out is always allowed (a machine can always exit), so it skips those checks.
Path parameters
string
required
Machine DID (
did:peaq:<decimal machine id>) or the bare decimal machine ID. An address-form DID (did:peaq:0x...) or a raw address returns 400 INVALID_REQUEST.Request body
boolean
required
true to opt in, false to opt out. Must be a JSON boolean (not "true" or 1).integer
required
Unix seconds when the message was signed. Must be a positive JSON integer inside the freshness window (see below).
string
required
The EIP-191 signature:
0x followed by exactly 130 hex characters (65 bytes). When signer_pubkey is present, a base58 Ed25519 signature of at most 88 characters instead.string
For a machine homed on Solana: the owner’s base58 Ed25519 public key (at most 44 characters). When present, the server verifies
signature as a base58 Ed25519 signature by this key over the Solana canonical message instead of EIP-191, and only the machine’s owner may sign. Sending it for a peaq-homed machine returns 403 UNAUTHORIZED_SIGNER. null is rejected with 400 INVALID_REQUEST; omit the field for the EIP-191 path.Canonical message
The client must build and sign this exact string, byte for byte. Fields are LF-separated (\n) with no trailing newline. For a peaq-homed machine (EIP-191):
registryis the server’s MachineRegistry address, lowercased. The server publishes it, withchain_id, atGET /.well-known/peaq-monetization.chain_idis the chain the server reads from. Together with the registry it binds the signature to one deployment, so a signature captured on one chain does not authorize the same action on another.machine_idis the decimal machine ID. Even when the URLkeyis a DID, the signed message uses the resolved decimal ID.opted_inis the lowercase stringtrueorfalse, matching the body field.
personal_sign (JS) or eth_account’s encode_defunct(text=message) (Python).
For a Solana-homed machine (Ed25519, with signer_pubkey in the body), the registry and chain_id lines are replaced by audience and home_chain:
audienceis the chain ID of the server’s deployment (thechain_idpublished atGET /.well-known/peaq-monetization), so a signature cannot be replayed against another deployment that serves the same machine.home_chainis the machine’s home protocol chain ordinal (5for Solana), so a signature cannot be replayed if the machine relocates.
signMessage produces), and send the signature base58-encoded.
Both SDKs refuse a Solana-homed write before signing (SOLANA_MONETIZATION_UNVERIFIED), so this path is for direct HTTP calls. See Monetization opt-in.
Freshness window
Thetimestamp must fall within the freshness window: up to 300 seconds in the past and 30 seconds of future clock skew. Replaying an old signature after the window closes is rejected, and within the window a strictly newer timestamp is required to overwrite a previously applied decision (see STALE_SIGNATURE).
Response
200 OKError responses
Errors use a coded envelope:{"detail": {"code", "message"}}. Branch on code, never on message. Two responses carry no code: a body that is not valid JSON returns 422 with detail as a list of validation objects, and a caller over the rate limit gets 429 with the body {"error": "Rate limit exceeded: 90 per 1 minute"}.
Example
SDK and CLI support
For a peaq-homed machine both SDKs wrap this endpoint, building and signing the canonical message for you: see the opt-in SDK reference (optIn / optOut in JS, opt_in / opt_out in Python). The CLI exposes it as peaqos monetize opt-in | opt-out. For a Solana-homed machine the SDKs refuse before signing (SOLANA_MONETIZATION_UNVERIFIED); use the direct HTTP flow above.
Related endpoints
GET /machine/{key}/monetizationreads the current state without a signature.GET /mcr/{did}returns the machine’s credit rating.

