openapi.json ↗

API v1 · REST · JSON

Order and control
servers from code.

The mam-jahn.de customer API: query products and prices, order with credit, fetch credentials, start, reinstall and back up servers. Every key only has the permissions you choose – optionally only from your IPs.

54
endpoints in 11 areas
60/min
calls per key
Bearer
keys with permissions, IP lock and expiry

Base URLhttps://mam-jahn.de/mjapi.php/v1

Quick start

Your first call in three steps

  1. Create a keyIn the client area under Account › API keys: name, permissions, allowed IPs. The key is shown exactly once.
  2. TestEnter it under “Your key” above and press “Send request” at “Check key” – or with curl:
    curl -s https://mam-jahn.de/mjapi.php/v1/ping -H "Authorization: Bearer $MJ_KEY"
  3. GoTry with “Sandbox” first – the API then only pretends and changes nothing.

Keys & permissions

One key, exactly the permissions it needs

Every call sends the key in the header Authorization: Bearer mjk_…. A missing permission returns 403 missing_scope. If an IP list is set, the key only works from there (IPv4/IPv6, also networks such as /24 or /64).

  • account:readRead account and credit
  • invoices:readRead invoices
  • credit:topupTop up credit (create invoice) · currently not available
  • products:readRead products and prices
  • orders:createPlace orders paid with credit · currently not available
  • services:readRead services and servers
  • services:credentialsFetch credentials of new servers (once, 24 h) · currently not available
  • services:powerStart, stop, reboot servers · currently not available
  • services:manageConfigure servers (hostname, SSH key, password, rDNS, ISO) · currently not available
  • services:backupsCreate, restore, delete backups and snapshots · currently not available
  • services:reinstallReinstall servers (wipes the system disk) · currently not available
  • domains:readRead domains and prices, check availability · currently not available
  • domains:orderRegister and transfer domains (with credit) · currently not available
  • domains:manageChange nameservers, auth code, lock · currently not available
  • reseller:manageReseller: manage end customers, assignments, billing · currently not available

Errors & status

Clear codes, no guessing

Errors always look like {"error":{"code":"…","message":"…"}} – code is stable, message is for humans.

200 / 201 / 202
OK, created, started in the background
401
key missing, wrong, revoked or expired
402
insufficient credit – nothing ordered
403
missing permission or IP not allowed
404 / 405
unknown or wrong method
409 / 410
not possible right now · already fetched or expired
422
invalid input
429
too many calls – wait a moment
502 / 503
platform not responding · API disabled

Sandbox

Try things without changing anything

With the header X-MJ-Sandbox: 1 the API checks key, permissions, IP and rate limit as usual – but executes nothing and answers with the example from this documentation. Nothing is ordered, reinstalled or deleted. The switch at the top sets the header for “Try it”.

Partner apps

“Connect with mam-jahn” in your app

  1. Register appWe register your app: name, redirect address, server IPs, optional webhook. You receive client ID, client secret and webhook secret.
  2. Send customershttps://mam-jahn.de/index.php?m=mj_api&a=connect&client_id=…&redirect_uri=…&state=…&scope=orders:create services:credentials
  3. Exchange codeThe customer confirms and returns with ?code=…&state=…. Your server exchanges the code via POST /oauth/token for a key for this customer only. App keys only see servers ordered via the app.
  4. Webhook service.readyCredentials of a new server, exactly once. Verify: X-MJ-Signature = HMAC-SHA256(X-MJ-Timestamp + "." + body, webhook-secret)

General

Schlüssel prüfen und die maschinenlesbare Beschreibung.

GET/ping

Check key

Returns client ID and the key's permissions – ideal as a first test.

any key 200

Possible errors

401
unauthorized Schlüssel fehlt, ist falsch oder widerrufen
403
ip_not_allowed Aufruf von einer nicht erlaubten IP
403
account_email E-Mail des Kontoinhabers nicht bestätigt
403
account_approval Neukunde, API noch nicht freigeschaltet
403
account_product kein aktiver Vertrag
curl -s "https://mam-jahn.de/mjapi.php/v1/ping" \
  -H "Authorization: Bearer $MJ_KEY"

Response · 200

{
    "ok": true,
    "client_id": 42,
    "scopes": [
        "account:read",
        "services:read"
    ],
    "sandbox": false,
    "time": "2026-10-19T12:00:00+02:00"
}

Try itLive

GET/openapi.json

OpenAPI document

All endpoints as OpenAPI 3.1 – for Postman, Insomnia, Swagger UI or client generators. No key needed.

no key 200

curl -s "https://mam-jahn.de/mjapi.php/v1/openapi.json"

Response · 200

{
    "openapi": "3.1.0",
    "info": {
        "title": "mam-jahn.de API",
        "version": "1.0"
    },
    "paths": {
        "…": []
    }
}

Try itLive

POST/oauth/token

Partner app: code for key

Partner apps only: after “Connect with mam-jahn” the customer returns with ?code=…. The app's server exchanges this code (10 minutes, once) for a key for this customer only.

no key 200 partner apps only

Parameters

grant_typeBody · Text · required
immer authorization_code
codeBody · Text · required
Code aus dem Rücksprung
client_idBody · Text · required
Client-ID der App
client_secretBody · Text · required
Client-Secret der App
redirect_uriBody · Text · required
dieselbe Rücksprung-Adresse wie beim Verbinden

Possible errors

401
invalid_client Client-ID oder Secret falsch
400
invalid_grant Code ungültig, abgelaufen oder benutzt
403
ip_not_allowed nicht von den Server-IPs der App
curl -s -X POST "https://mam-jahn.de/mjapi.php/v1/oauth/token" \
  -H "Content-Type: application/json" \
  -d '{"grant_type":"authorization_code","code":"Rk2…","client_id":"mja_1a2b3c4d5e6f","client_secret":"mjs_…","redirect_uri":"https://app.example.de/connect/callback"}'

Response · 200

{
    "access_token": "mjk_77be2210_…",
    "token_type": "Bearer",
    "scope": "account:read orders:create services:read services:credentials",
    "client_id": 42
}

Try itLive

Public (website)

Katalog, Preise, Steuersätze, Status und Rechtstexte für Websites – ohne Schlüssel, nur öffentliche Daten.

GET/public/catalog

Public catalog

All product lines with plans, net prices per term (1/3/6/12 months, tiers 0/3/7/13 %), specs and order links (order_url, since v1.2 also order_urls per term), plus tax rates, operating systems, domain prices, figures, node status, network and links. All amounts net (*_net). Public data only, no key needed. Response cached for 5 minutes (Cache-Control, ETag; 304 with If-None-Match). CORS only for registered website origins. Contract: version 1 (extensions v1.1 info blocks, v1.2 order_urls, v1.3 exchange = KVM exchange offers, strike-through price only with a documented regular price, v1.4 trial = free test server, only when enabled and the security group was checked as present, v1.6 links.service_bot = invite of the Discord service bot, only when set), new fields are backward compatible.

no key 200

Possible errors

429
rate_limited Zu viele Anfragen von dieser IP
503
unavailable Daten gerade nicht verfügbar
curl -s "https://mam-jahn.de/mjapi.php/v1/public/catalog"

Response · 200

{
    "version": 1,
    "generated_at": "2026-11-01T12:00:00+01:00",
    "source": "whmcs",
    "currency": {
        "code": "EUR",
        "prefix": "",
        "suffix": " €",
        "decimals": 2,
        "format": "de"
    },
    "tax": {
        "prices_are": "net",
        "default_country": "DE",
        "rates": {
            "DE": 19,
            "AT": 20
        }
    },
    "terms": [
        {
            "months": 1,
            "discount_pct": 0
        },
        {
            "months": 3,
            "discount_pct": 3
        },
        {
            "months": 6,
            "discount_pct": 7
        },
        {
            "months": 12,
            "discount_pct": 13
        }
    ],
    "groups": [
        {
            "key": "server",
            "name": "Eigener Server"
        }
    ],
    "lines": [
        {
            "slug": "vps",
            "name": "VPS",
            "group": "server",
            "summary": "Geteilte Kerne, voller Root-Zugriff",
            "hardware": "AMD EPYC 7763",
            "virtualization": "KVM",
            "location": "Frankfurt am Main",
            "features": [
                "Laufzeit frei wählbar: 1, 3, 6 oder 12 Monate"
            ],
            "from_net": 7.9,
            "order_url": "https://mam-jahn.de/vps",
            "plans": [
                {
                    "id": 12,
                    "name": "VPS 8",
                    "popular": false,
                    "available": true,
                    "specs": [
                        {
                            "key": "vcores",
                            "value": 4
                        },
                        {
                            "key": "ram",
                            "value": 8,
                            "unit": "GB"
                        },
                        {
                            "key": "disk",
                            "value": 120,
                            "unit": "GB",
                            "note": "NVMe"
                        }
                    ],
                    "prices_net": {
                        "1": 13.9,
                        "3": 13.48,
                        "6": 12.93,
                        "12": 12.09
                    },
                    "setup_net": 0,
                    "order_url": "https://mam-jahn.de/cart.php?a=add&pid=12&billingcycle=monthly",
                    "order_urls": {
                        "1": "https://mam-jahn.de/cart.php?a=add&pid=12&billingcycle=monthly",
                        "3": "https://mam-jahn.de/cart.php?a=add&pid=12&billingcycle=quarterly",
                        "6": "https://mam-jahn.de/cart.php?a=add&pid=12&billingcycle=semiannually",
                        "12": "https://mam-jahn.de/cart.php?a=add&pid=12&billingcycle=annually"
                    }
                }
            ]
        }
    ],
    "os": [
        {
            "family": "Debian",
            "versions": [
                "12",
                "13"
            ]
        }
    ],
    "exchange": {
        "about": [
            "Jeden Abend entstehen neue Angebote aus freier Kapazität."
        ],
        "next_at": "2026-11-01T20:00:00+01:00",
        "offers": [
            {
                "id": "231",
                "line": "ryzen",
                "name": "Ryzen Deal #1",
                "hardware": "AMD Ryzen 9 9950X",
                "specs": [
                    {
                        "key": "vcores",
                        "value": 4,
                        "note": "geteilt"
                    },
                    {
                        "key": "ram",
                        "value": 8,
                        "unit": "GB",
                        "note": "DDR5 ECC"
                    },
                    {
                        "key": "disk",
                        "value": 150,
                        "unit": "GB",
                        "note": "NVMe SSD"
                    }
                ],
                "price_net": 7.5,
                "regular_net": 10,
                "discount_pct": 25,
                "order_url": "https://mam-jahn.de/cart.php?a=add&pid=231&billingcycle=monthly",
                "available": true,
                "until": "2026-11-01T20:00:00+01:00"
            }
        ]
    },
    "trial": {
        "enabled": true,
        "hours": 24,
        "specs": [
            {
                "key": "vcores",
                "value": 2
            },
            {
                "key": "ram",
                "value": 4,
                "unit": "GB"
            },
            {
                "key": "disk",
                "value": 40,
                "unit": "GB",
                "note": "NVMe"
            }
        ],
        "request_url": "https://mam-jahn.de/testen"
    },
    "domains": [
        {
            "tld": ".de",
            "register_net": 4.9,
            "renew_net": 4.9,
            "transfer_net": 0
        }
    ],
    "stats": {
        "threads": 228,
        "ram_gb": 1408,
        "nvme_tb": 73,
        "services_active": 62
    },
    "status": {
        "updated_at": "2026-11-01T11:58:00+01:00",
        "nodes_online": 5,
        "nodes_total": 5,
        "cpu_pct": 9,
        "nodes": [
            {
                "name": "EPYC 01",
                "online": true,
                "cpu_pct": 12
            }
        ]
    },
    "network": {
        "asn": "AS201687",
        "location": "Frankfurt am Main",
        "uplinks": [
            {
                "name": "EPYC 01",
                "gbit": 20
            }
        ]
    },
    "links": {
        "cart": "https://mam-jahn.de/cart.php?a=view",
        "login": "https://mam-jahn.de/login",
        "register": "https://mam-jahn.de/register.php",
        "status": "https://mam-jahn.de/status",
        "cancel": "https://mam-jahn.de/kuendigen",
        "contact": "https://mam-jahn.de/contact.php",
        "api_docs": "https://mam-jahn.de/api-docs",
        "discord": "https://discord.gg/E9wzeKCtQr"
    }
}

Try itLive

Account

Konto, Guthaben, Rechnungen und deine API-Aufrufe.

GET/me

Get account

Name, email, country, currency and current credit.

account:read 200

curl -s "https://mam-jahn.de/mjapi.php/v1/me" \
  -H "Authorization: Bearer $MJ_KEY"

Response · 200

{
    "id": 42,
    "firstname": "Max",
    "lastname": "Muster",
    "company": "",
    "email": "max@example.de",
    "country": "DE",
    "currency": "EUR",
    "credit": 40
}

Try itLive

GET/invoices

List invoices

Invoices with payment link, newest first.

invoices:read 200

Parameters

statusQuery · Text
Paid, Unpaid, Cancelled oder Refunded
limitQuery · integer
1–200, Standard 50
curl -s "https://mam-jahn.de/mjapi.php/v1/invoices" \
  -H "Authorization: Bearer $MJ_KEY"

Response · 200

{
    "invoices": [
        {
            "id": 1290,
            "number": "R-2026-0412",
            "date": "2026-10-19",
            "due": "2026-10-19",
            "paid": "",
            "total": 25,
            "status": "Unpaid",
            "pay_url": "https://mam-jahn.de/viewinvoice.php?id=1290"
        }
    ]
}

Try itLive

POST/credit/topup

Top up credit

Creates a top-up invoice. Once paid via the link, the amount is added as credit.

credit:topup 201

Parameters

amountBody · number · required
Betrag in deiner Währung (Mindest- und Höchstbetrag wie im Kundenbereich)

Possible errors

422
invalid_amount Betrag außerhalb der Grenzen
409
topup_disabled Aufladen ist abgeschaltet
curl -s -X POST "https://mam-jahn.de/mjapi.php/v1/credit/topup" \
  -H "Authorization: Bearer $MJ_KEY" \
  -H "Content-Type: application/json" \
  -d '{"amount":25}'

Response · 201

{
    "invoice_id": 1291,
    "amount": 25,
    "pay_url": "https://mam-jahn.de/viewinvoice.php?id=1291"
}

Try itLive

GET/requests

Own requests

Your account's latest API calls (30 days) with status, IP and duration. Keys and passwords are never stored.

account:read 200

Parameters

limitQuery · integer
1–500, Standard 100
curl -s "https://mam-jahn.de/mjapi.php/v1/requests" \
  -H "Authorization: Bearer $MJ_KEY"

Response · 200

{
    "requests": [
        {
            "time": "2026-10-19 11:58:02",
            "method": "GET",
            "path": "/v1/services",
            "status": 200,
            "ip": "203.0.113.10",
            "ms": 38,
            "key": "mjk_3f9a01c2",
            "note": ""
        }
    ]
}

Try itLive

Ordering

Produkte mit Preisen und Bestellen mit Guthaben.

GET/products

List products

All products orderable via the API with prices per billing cycle.

products:read 200

curl -s "https://mam-jahn.de/mjapi.php/v1/products" \
  -H "Authorization: Bearer $MJ_KEY"

Response · 200

{
    "products": [
        {
            "id": 12,
            "name": "KVM S",
            "group": "KVM Server",
            "module": "mjpve",
            "currency": "EUR",
            "in_stock": true,
            "prices": {
                "monthly": {
                    "price": 9.9,
                    "setup": 0
                },
                "annually": {
                    "price": 99,
                    "setup": 0
                }
            }
        }
    ]
}

Try itLive

GET/products/{id}

Get product

One product with options (configoptions, e.g. operating system) and fields (customfields) for ordering.

products:read 200

Parameters

idpath · integer · required
Produkt-ID

Possible errors

404
not_found Produkt nicht über die API bestellbar
curl -s "https://mam-jahn.de/mjapi.php/v1/products/12" \
  -H "Authorization: Bearer $MJ_KEY"

Response · 200

{
    "id": 12,
    "name": "KVM S",
    "group": "KVM Server",
    "module": "mjpve",
    "currency": "EUR",
    "in_stock": true,
    "prices": {
        "monthly": {
            "price": 9.9,
            "setup": 0
        }
    },
    "description": "2 vCores, 4 GB RAM, 40 GB NVMe",
    "configoptions": [
        {
            "id": 7,
            "name": "Betriebssystem",
            "type": "dropdown",
            "choices": [
                {
                    "id": 31,
                    "name": "Debian 12",
                    "prices": {
                        "monthly": {
                            "price": 0,
                            "setup": 0
                        }
                    }
                }
            ]
        }
    ],
    "customfields": [
        {
            "id": 5,
            "name": "SSH Key",
            "type": "textarea",
            "required": false,
            "description": ""
        }
    ]
}

Try itLive

POST/orders

Place order

Orders a product, paid with credit by default. If credit is insufficient nothing is ordered. The server is then set up automatically – check GET /v1/services/{id}.

orders:create 201

Parameters

product_idBody · integer · required
Produkt-ID aus GET /v1/products
billingcycleBody · Text · required
monthly, quarterly, semiannually, annually (24/36 Monate nicht mehr bestellbar)
hostnameBody · Text
Hostname des Servers
configoptionsBody · object
Option-ID => Auswahl-ID (bzw. Menge)
customfieldsBody · object
Feld-ID => Wert
payBody · Text
credit (Standard) oder invoice (Rechnung offen lassen)
promocodeBody · Text
Gutscheincode
customer_idBody · integer
nur Reseller: Endkunde, dem der Server zugeordnet wird

Possible errors

402
insufficient_credit Guthaben reicht nicht – nichts bestellt
422
invalid_billingcycle Laufzeit nicht angeboten
422
invalid_configoption Option oder Auswahl unbekannt
409
out_of_stock nicht verfügbar
404
not_found Endkunde nicht gefunden (customer_id)
curl -s -X POST "https://mam-jahn.de/mjapi.php/v1/orders" \
  -H "Authorization: Bearer $MJ_KEY" \
  -H "Content-Type: application/json" \
  -d '{"product_id":12,"billingcycle":"monthly","hostname":"node1.example.de","configoptions":{"7":31},"customfields":{"5":"ssh-ed25519 AAAA… user@pc"},"pay":"credit","customer_id":15}'

Response · 201

{
    "order_id": 512,
    "service_id": 877,
    "invoice_id": 1290,
    "total": 9.9,
    "payment": "paid",
    "pay_url": null,
    "next": "GET /v1/services/877 bis status Active, dann einmal GET /v1/services/877/credentials"
}

Try itLive

Services

Alle Verträge und die Zugangsdaten neuer Server.

GET/services

List services

All services with status, hostname and IPs. Partner app keys only see what was ordered via the app.

services:read 200

Parameters

customer_idQuery · integer
nur Reseller: nur Verträge dieses Endkunden
curl -s "https://mam-jahn.de/mjapi.php/v1/services" \
  -H "Authorization: Bearer $MJ_KEY"

Response · 200

{
    "services": [
        {
            "id": 877,
            "product_id": 12,
            "product": "KVM S",
            "module": "mjpve",
            "status": "Active",
            "hostname": "node1.example.de",
            "ipv4": "203.0.113.25",
            "ips": [
                "2001:db8:25::1/64"
            ],
            "billingcycle": "monthly",
            "amount": 9.9,
            "registered": "2026-10-19",
            "next_due": "2026-11-19"
        }
    ]
}

Try itLive

GET/services/{id}

Get service

One service. credentials shows whether credentials can be fetched: ok, fetched, expired or none.

services:read 200

Parameters

idpath · integer · required
ID des Vertrags (Dienst), z. B. aus GET /v1/services

Possible errors

404
not_found Vertrag nicht gefunden
curl -s "https://mam-jahn.de/mjapi.php/v1/services/877" \
  -H "Authorization: Bearer $MJ_KEY"

Response · 200

{
    "id": 877,
    "product": "KVM S",
    "status": "Active",
    "hostname": "node1.example.de",
    "ipv4": "203.0.113.25",
    "credentials": "ok"
}

Try itLive

GET/services/{id}/credentials

Fetch credentials

IPv4, user and root password of a server ordered via the API – exactly once and at most 24 hours after setup.

services:credentials 200

Parameters

idpath · integer · required
ID des Vertrags (Dienst), z. B. aus GET /v1/services

Possible errors

409
not_ready Server noch nicht eingerichtet
410
credentials_fetched schon abgeholt
410
credentials_expired Abholzeit abgelaufen
curl -s "https://mam-jahn.de/mjapi.php/v1/services/877/credentials" \
  -H "Authorization: Bearer $MJ_KEY"

Response · 200

{
    "service_id": 877,
    "hostname": "node1.example.de",
    "ipv4": "203.0.113.25",
    "ipv4_all": [
        "203.0.113.25"
    ],
    "ipv6": [
        "2001:db8:25::1/64"
    ],
    "username": "root",
    "password": "Xk7#q2…"
}

Try itLive

Server

Status, Power, Neuinstallation, Hostname, SSH-Key, Passwort.

GET/services/{id}/status

Server status

Is the server running? Plus CPU, RAM, disks, uptime and whether the guest agent responds.

services:read 200

Parameters

idpath · integer · required
ID des Vertrags (Dienst), z. B. aus GET /v1/services

Possible errors

404
not_found Vertrag nicht gefunden oder für diesen Schlüssel nicht sichtbar
409
not_supported Kein Proxmox-Server oder nicht aktiv
curl -s "https://mam-jahn.de/mjapi.php/v1/services/877/status" \
  -H "Authorization: Bearer $MJ_KEY"

Response · 200

{
    "status": "running",
    "uptime": 86400,
    "cpus": 2,
    "cpu": 3.4,
    "mem": 1073741824,
    "maxmem": 4294967296,
    "disk": 0,
    "maxdisk": 42949672960,
    "netin": 1203391,
    "netout": 893221,
    "agent": true,
    "disks": [
        {
            "mount": "/",
            "used": 6442450944,
            "total": 42949672960
        }
    ]
}

Try itLive

POST/services/{id}/power

Start, stop, reboot

start, shutdown (graceful), stop (hard off), reboot, reset (hard reboot). At most one action every 8 seconds per server.

services:power 200

Parameters

idpath · integer · required
ID des Vertrags (Dienst), z. B. aus GET /v1/services
actionBody · Text · required
start, shutdown, stop, reboot oder reset

Possible errors

404
not_found Vertrag nicht gefunden oder für diesen Schlüssel nicht sichtbar
409
not_supported Kein Proxmox-Server oder nicht aktiv
429
too_fast zu schnell hintereinander
curl -s -X POST "https://mam-jahn.de/mjapi.php/v1/services/877/power" \
  -H "Authorization: Bearer $MJ_KEY" \
  -H "Content-Type: application/json" \
  -d '{"action":"reboot"}'

Response · 200

{
    "ok": true,
    "action": "reboot",
    "upid": "UPID:n2:0012A3F1:…"
}

Try itLive

GET/services/{id}/os

Operating systems and ISOs

Templates for reinstalling (kind template) and mountable ISO files (kind iso) for this server.

services:read 200

Parameters

idpath · integer · required
ID des Vertrags (Dienst), z. B. aus GET /v1/services

Possible errors

404
not_found Vertrag nicht gefunden oder für diesen Schlüssel nicht sichtbar
409
not_supported Kein Proxmox-Server oder nicht aktiv
curl -s "https://mam-jahn.de/mjapi.php/v1/services/877/os" \
  -H "Authorization: Bearer $MJ_KEY"

Response · 200

{
    "items": [
        {
            "key": "debian-12",
            "kind": "template",
            "name": "Debian 12",
            "windows": false
        },
        {
            "key": "local:iso/rescue.iso",
            "kind": "iso",
            "name": "Rettungssystem"
        }
    ]
}

Try itLive

POST/services/{id}/reinstall

Reinstall

Reinstalls the chosen operating system – all data on the system disk is lost. Runs in the background; check GET /v1/services/{id}/jobs/{job}.

services:reinstall 202

Parameters

idpath · integer · required
ID des Vertrags (Dienst), z. B. aus GET /v1/services
templateBody · Text · required
key aus GET /v1/services/{id}/os (kind template)
hostnameBody · Text · required
Hostname nach der Installation
confirmBody · Text · required
zur Sicherheit: der aktuelle Hostname des Servers
sshkeyBody · Text
öffentlicher SSH-Schlüssel (nicht bei Windows)

Possible errors

404
not_found Vertrag nicht gefunden oder für diesen Schlüssel nicht sichtbar
409
not_supported Kein Proxmox-Server oder nicht aktiv
422
confirm confirm passt nicht zum aktuellen Hostnamen
422
invalid_template Vorlage unbekannt
409
busy es läuft schon ein Auftrag
curl -s -X POST "https://mam-jahn.de/mjapi.php/v1/services/877/reinstall" \
  -H "Authorization: Bearer $MJ_KEY" \
  -H "Content-Type: application/json" \
  -d '{"template":"debian-12","hostname":"node1.example.de","confirm":"node1.example.de","sshkey":"ssh-ed25519 AAAA… user@pc"}'

Response · 202

{
    "job": 3051
}

Try itLive

GET/services/{id}/jobs/{job}

Get job

State of a reinstall: queued, running, done or error.

services:read 200

Parameters

idpath · integer · required
ID des Vertrags (Dienst), z. B. aus GET /v1/services
jobpath · integer · required
Auftrags-ID aus reinstall

Possible errors

404
not_found Vertrag nicht gefunden oder für diesen Schlüssel nicht sichtbar
409
not_supported Kein Proxmox-Server oder nicht aktiv
curl -s "https://mam-jahn.de/mjapi.php/v1/services/877/jobs/3051" \
  -H "Authorization: Bearer $MJ_KEY"

Response · 200

{
    "status": "running",
    "error": ""
}

Try itLive

POST/services/{id}/password-reset

Reset root password

Sets a new random root password and returns it. Immediately with the guest agent, otherwise on next boot (reboot = true).

services:manage 200

Parameters

idpath · integer · required
ID des Vertrags (Dienst), z. B. aus GET /v1/services

Possible errors

404
not_found Vertrag nicht gefunden oder für diesen Schlüssel nicht sichtbar
409
not_supported Kein Proxmox-Server oder nicht aktiv
422
no_agent Gast-Agent nicht erreichbar
curl -s -X POST "https://mam-jahn.de/mjapi.php/v1/services/877/password-reset" \
  -H "Authorization: Bearer $MJ_KEY"

Response · 200

{
    "pw": "Qm4!x9…",
    "method": "agent",
    "reboot": false
}

Try itLive

POST/services/{id}/hostname

Change hostname

Changes the hostname (also in the client area and the server name DNS).

services:manage 200

Parameters

idpath · integer · required
ID des Vertrags (Dienst), z. B. aus GET /v1/services
hostnameBody · Text · required
neuer Hostname

Possible errors

404
not_found Vertrag nicht gefunden oder für diesen Schlüssel nicht sichtbar
409
not_supported Kein Proxmox-Server oder nicht aktiv
422
invalid_hostname Hostname ungültig
curl -s -X POST "https://mam-jahn.de/mjapi.php/v1/services/877/hostname" \
  -H "Authorization: Bearer $MJ_KEY" \
  -H "Content-Type: application/json" \
  -d '{"hostname":"node2.example.de"}'

Response · 200

{
    "reboot": true
}

Try itLive

POST/services/{id}/sshkey

Set SSH key

Stores public SSH keys via cloud-init (effective after next boot). We deliberately never generate private keys.

services:manage 200

Parameters

idpath · integer · required
ID des Vertrags (Dienst), z. B. aus GET /v1/services
keyBody · Text · required
ein oder mehrere öffentliche Schlüssel, je Zeile

Possible errors

404
not_found Vertrag nicht gefunden oder für diesen Schlüssel nicht sichtbar
409
not_supported Kein Proxmox-Server oder nicht aktiv
422
invalid_sshkey Schlüssel ungültig
curl -s -X POST "https://mam-jahn.de/mjapi.php/v1/services/877/sshkey" \
  -H "Authorization: Bearer $MJ_KEY" \
  -H "Content-Type: application/json" \
  -d '{"key":"ssh-ed25519 AAAA… user@pc"}'

Response · 200

{
    "reboot": true
}

Try itLive

Metrics

Auslastung, Verlauf, Traffic und Aufgaben.

GET/services/{id}/metrics

History

Time series for CPU (%), RAM (bytes), network and disk (bytes/s).

services:read 200

Parameters

idpath · integer · required
ID des Vertrags (Dienst), z. B. aus GET /v1/services
timeframeQuery · Text
hour, day, week, month oder year

Possible errors

404
not_found Vertrag nicht gefunden oder für diesen Schlüssel nicht sichtbar
409
not_supported Kein Proxmox-Server oder nicht aktiv
curl -s "https://mam-jahn.de/mjapi.php/v1/services/877/metrics" \
  -H "Authorization: Bearer $MJ_KEY"

Response · 200

{
    "t": [
        1760868000,
        1760868060
    ],
    "cpu": [
        2.1,
        3.4
    ],
    "mem": [
        1073741824,
        1081081856
    ],
    "maxmem": 4294967296,
    "netin": [
        1200,
        900
    ],
    "netout": [
        800,
        640
    ],
    "diskread": [
        0,
        4096
    ],
    "diskwrite": [
        12288,
        8192
    ]
}

Try itLive

GET/services/{id}/traffic

Traffic

Traffic of the last 24 hours (basis of fair-use throttling) and history in steps.

services:read 200

Parameters

idpath · integer · required
ID des Vertrags (Dienst), z. B. aus GET /v1/services
daysQuery · integer
1–31 Tage Verlauf, Standard 1
stepQuery · integer
Schritt in Sekunden (mind. 900), Standard 3600

Possible errors

404
not_found Vertrag nicht gefunden oder für diesen Schlüssel nicht sichtbar
409
not_supported Kein Proxmox-Server oder nicht aktiv
curl -s "https://mam-jahn.de/mjapi.php/v1/services/877/traffic" \
  -H "Authorization: Bearer $MJ_KEY"

Response · 200

{
    "last24h": {
        "rx": 0,
        "tx": 0,
        "total": 5368709120
    },
    "limit_gb": 1000,
    "throttle_mbit": 100,
    "series": [
        {
            "t": 1760868000,
            "rx": 104857600,
            "tx": 52428800
        }
    ]
}

Try itLive

GET/services/{id}/tasks

Recent tasks

Recent server tasks (start, backup, snapshot …). With ?upid=… the state of a single task.

services:read 200

Parameters

idpath · integer · required
ID des Vertrags (Dienst), z. B. aus GET /v1/services
upidQuery · Text
eine Aufgabe, z. B. aus backups oder power

Possible errors

404
not_found Vertrag nicht gefunden oder für diesen Schlüssel nicht sichtbar
409
not_supported Kein Proxmox-Server oder nicht aktiv
curl -s "https://mam-jahn.de/mjapi.php/v1/services/877/tasks" \
  -H "Authorization: Bearer $MJ_KEY"

Response · 200

{
    "tasks": [
        {
            "upid": "UPID:n2:0012A3F1:…",
            "type": "vzdump",
            "status": "OK",
            "start": 1760868000,
            "end": 1760868120
        }
    ]
}

Try itLive

Backups & snapshots

Sichern, wiederherstellen, löschen.

GET/services/{id}/backups

List backups

All backups with size, note, protection and the plan's limit.

services:read 200

Parameters

idpath · integer · required
ID des Vertrags (Dienst), z. B. aus GET /v1/services

Possible errors

404
not_found Vertrag nicht gefunden oder für diesen Schlüssel nicht sichtbar
409
not_supported Kein Proxmox-Server oder nicht aktiv
curl -s "https://mam-jahn.de/mjapi.php/v1/services/877/backups" \
  -H "Authorization: Bearer $MJ_KEY"

Response · 200

{
    "items": [
        {
            "volid": "backup:backup/vm/1203/2026-10-19T02:00:00Z",
            "time": 1760839200,
            "size": 3221225472,
            "note": "vor Update",
            "protected": false
        }
    ],
    "limit": 3
}

Try itLive

POST/services/{id}/backups

Create backup

Starts a backup in the background. State via GET /v1/services/{id}/tasks?upid=…

services:backups 202

Parameters

idpath · integer · required
ID des Vertrags (Dienst), z. B. aus GET /v1/services
noteBody · Text
Notiz zum Backup

Possible errors

404
not_found Vertrag nicht gefunden oder für diesen Schlüssel nicht sichtbar
409
not_supported Kein Proxmox-Server oder nicht aktiv
422
limit Limit des Tarifs erreicht
409
busy es läuft schon ein Backup
curl -s -X POST "https://mam-jahn.de/mjapi.php/v1/services/877/backups" \
  -H "Authorization: Bearer $MJ_KEY" \
  -H "Content-Type: application/json" \
  -d '{"note":"vor Update"}'

Response · 202

{
    "upid": "UPID:n2:0012A3F1:…"
}

Try itLive

POST/services/{id}/backups/restore

Restore backup

Restores a backup – the current state is overwritten.

services:backups 202

Parameters

idpath · integer · required
ID des Vertrags (Dienst), z. B. aus GET /v1/services
volidBody · Text · required
volid aus GET /v1/services/{id}/backups

Possible errors

404
not_found Vertrag nicht gefunden oder für diesen Schlüssel nicht sichtbar
409
not_supported Kein Proxmox-Server oder nicht aktiv
curl -s -X POST "https://mam-jahn.de/mjapi.php/v1/services/877/backups/restore" \
  -H "Authorization: Bearer $MJ_KEY" \
  -H "Content-Type: application/json" \
  -d '{"volid":"backup:backup/vm/1203/2026-10-19T02:00:00Z"}'

Response · 202

{
    "upid": "UPID:n2:0012B001:…"
}

Try itLive

DELETE/services/{id}/backups

Delete backup

Deletes a backup (unprotect protected backups first).

services:backups 200

Parameters

idpath · integer · required
ID des Vertrags (Dienst), z. B. aus GET /v1/services
volidBody · Text · required
volid des Backups

Possible errors

404
not_found Vertrag nicht gefunden oder für diesen Schlüssel nicht sichtbar
409
not_supported Kein Proxmox-Server oder nicht aktiv
curl -s -X DELETE "https://mam-jahn.de/mjapi.php/v1/services/877/backups" \
  -H "Authorization: Bearer $MJ_KEY" \
  -H "Content-Type: application/json" \
  -d '{"volid":"backup:backup/vm/1203/2026-10-19T02:00:00Z"}'

Response · 200

{
    "ok": true
}

Try itLive

GET/services/{id}/snapshots

List snapshots

All snapshots, the current state and the plan's limit.

services:read 200

Parameters

idpath · integer · required
ID des Vertrags (Dienst), z. B. aus GET /v1/services

Possible errors

404
not_found Vertrag nicht gefunden oder für diesen Schlüssel nicht sichtbar
409
not_supported Kein Proxmox-Server oder nicht aktiv
curl -s "https://mam-jahn.de/mjapi.php/v1/services/877/snapshots" \
  -H "Authorization: Bearer $MJ_KEY"

Response · 200

{
    "items": [
        {
            "name": "vor_update",
            "description": "",
            "time": 1760868000,
            "vmstate": false
        }
    ],
    "limit": 3,
    "current": "vor_update"
}

Try itLive

POST/services/{id}/snapshots

Create snapshot

Creates a snapshot (name: letters, digits, _ and -).

services:backups 202

Parameters

idpath · integer · required
ID des Vertrags (Dienst), z. B. aus GET /v1/services
nameBody · Text · required
Name des Snapshots
descriptionBody · Text
Beschreibung

Possible errors

404
not_found Vertrag nicht gefunden oder für diesen Schlüssel nicht sichtbar
409
not_supported Kein Proxmox-Server oder nicht aktiv
422
invalid_name Name ungültig
422
limit Limit erreicht
curl -s -X POST "https://mam-jahn.de/mjapi.php/v1/services/877/snapshots" \
  -H "Authorization: Bearer $MJ_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"vor_update","description":"vor dem Kernel-Update"}'

Response · 202

{
    "upid": "UPID:n2:0012C9D0:…"
}

Try itLive

POST/services/{id}/snapshots/rollback

Roll back snapshot

Rolls the server back to the snapshot.

services:backups 202

Parameters

idpath · integer · required
ID des Vertrags (Dienst), z. B. aus GET /v1/services
nameBody · Text · required
Name des Snapshots

Possible errors

404
not_found Vertrag nicht gefunden oder für diesen Schlüssel nicht sichtbar
409
not_supported Kein Proxmox-Server oder nicht aktiv
curl -s -X POST "https://mam-jahn.de/mjapi.php/v1/services/877/snapshots/rollback" \
  -H "Authorization: Bearer $MJ_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"vor_update"}'

Response · 202

{
    "upid": "UPID:n2:0012D1E4:…"
}

Try itLive

DELETE/services/{id}/snapshots

Delete snapshot

Deletes a snapshot.

services:backups 200

Parameters

idpath · integer · required
ID des Vertrags (Dienst), z. B. aus GET /v1/services
nameBody · Text · required
Name des Snapshots

Possible errors

404
not_found Vertrag nicht gefunden oder für diesen Schlüssel nicht sichtbar
409
not_supported Kein Proxmox-Server oder nicht aktiv
curl -s -X DELETE "https://mam-jahn.de/mjapi.php/v1/services/877/snapshots" \
  -H "Authorization: Bearer $MJ_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"vor_update"}'

Response · 200

{
    "upid": "UPID:n2:0012D2F0:…"
}

Try itLive

Network

IPs, rDNS, ISO-Laufwerk und Firewall.

GET/services/{id}/network

IPs and rDNS

All IPv4/IPv6 of the server with gateway and rDNS entry.

services:read 200

Parameters

idpath · integer · required
ID des Vertrags (Dienst), z. B. aus GET /v1/services

Possible errors

404
not_found Vertrag nicht gefunden oder für diesen Schlüssel nicht sichtbar
409
not_supported Kein Proxmox-Server oder nicht aktiv
curl -s "https://mam-jahn.de/mjapi.php/v1/services/877/network" \
  -H "Authorization: Bearer $MJ_KEY"

Response · 200

{
    "ips": [
        {
            "ip": "203.0.113.25",
            "version": 4,
            "gateway": "203.0.113.1",
            "rdns": "node1.example.de",
            "rdns_default": "static-203-0-113-25.clients.example.net"
        }
    ]
}

Try itLive

POST/services/{id}/rdns

Set rDNS

Sets the reverse DNS entry of one of the server's IPs. Empty name = default.

services:manage 200

Parameters

idpath · integer · required
ID des Vertrags (Dienst), z. B. aus GET /v1/services
ipBody · Text · required
IP des Servers
nameBody · Text · required
Name (FQDN)

Possible errors

404
not_found Vertrag nicht gefunden oder für diesen Schlüssel nicht sichtbar
409
not_supported Kein Proxmox-Server oder nicht aktiv
422
invalid_ip IP gehört nicht zum Server
422
invalid_name Name ungültig
curl -s -X POST "https://mam-jahn.de/mjapi.php/v1/services/877/rdns" \
  -H "Authorization: Bearer $MJ_KEY" \
  -H "Content-Type: application/json" \
  -d '{"ip":"203.0.113.25","name":"mail.example.de"}'

Response · 200

{
    "ok": true
}

Try itLive

POST/services/{id}/iso

Mount / eject ISO

Mounts an ISO file in the virtual drive (key from /os with kind iso). Empty = eject.

services:manage 200

Parameters

idpath · integer · required
ID des Vertrags (Dienst), z. B. aus GET /v1/services
volidBody · Text
ISO-key oder leer zum Auswerfen

Possible errors

404
not_found Vertrag nicht gefunden oder für diesen Schlüssel nicht sichtbar
409
not_supported Kein Proxmox-Server oder nicht aktiv
422
invalid_iso ISO unbekannt
curl -s -X POST "https://mam-jahn.de/mjapi.php/v1/services/877/iso" \
  -H "Authorization: Bearer $MJ_KEY" \
  -H "Content-Type: application/json" \
  -d '{"volid":"local:iso/rescue.iso"}'

Response · 200

{
    "ok": true,
    "reboot": false
}

Try itLive

GET/services/{id}/firewall

Read firewall

Firewall state, default policies and all rules of the server.

services:read 200

Parameters

idpath · integer · required
ID des Vertrags (Dienst), z. B. aus GET /v1/services

Possible errors

404
not_found Vertrag nicht gefunden oder für diesen Schlüssel nicht sichtbar
409
not_supported Kein Proxmox-Server oder nicht aktiv
curl -s "https://mam-jahn.de/mjapi.php/v1/services/877/firewall" \
  -H "Authorization: Bearer $MJ_KEY"

Response · 200

{
    "enable": true,
    "policy_in": "DROP",
    "policy_out": "ACCEPT",
    "rules": [
        {
            "pos": 0,
            "type": "in",
            "action": "ACCEPT",
            "proto": "tcp",
            "dport": "22",
            "source": "",
            "comment": "SSH",
            "enable": true
        }
    ]
}

Try itLive

Domains

Verfügbarkeit, Preise, registrieren und umziehen mit Guthaben, Nameserver, Authcode, Sperre.

GET/domains/check

Check availability

Is the domain free? Plus your prices for registration, transfer and renewal (1 year).

domains:read 200

Parameters

domainQuery · Text · required
Domain mit Endung

Possible errors

422
invalid_domain Domain ungültig
429
rate_limited höchstens 30 Prüfungen je Minute
curl -s "https://mam-jahn.de/mjapi.php/v1/domains/check?domain=mein-projekt.de" \
  -H "Authorization: Bearer $MJ_KEY"

Response · 200

{
    "domain": "mein-projekt.de",
    "available": true,
    "tld": ".de",
    "offered": true,
    "prices": {
        "register": 3.51,
        "transfer": 3.51,
        "renew": 3.51
    }
}

Try itLive

GET/domains/pricing

Domain prices

All TLDs with your 1-year prices (registration, transfer, renewal).

domains:read 200

curl -s "https://mam-jahn.de/mjapi.php/v1/domains/pricing" \
  -H "Authorization: Bearer $MJ_KEY"

Response · 200

{
    "currency": "EUR",
    "tlds": [
        {
            "tld": ".de",
            "register": 3.51,
            "transfer": 3.51,
            "renew": 3.51
        },
        {
            "tld": ".com",
            "register": 16.6,
            "transfer": 16.6,
            "renew": 16.6
        }
    ]
}

Try itLive

GET/domains

List domains

All domains with status, expiry and renewal price.

domains:read 200

Parameters

customer_idQuery · integer
nur Reseller: nur Domains dieses Endkunden
curl -s "https://mam-jahn.de/mjapi.php/v1/domains" \
  -H "Authorization: Bearer $MJ_KEY"

Response · 200

{
    "domains": [
        {
            "id": 301,
            "domain": "mein-projekt.de",
            "status": "Active",
            "registered": "2026-10-19",
            "expires": "2027-10-19",
            "next_due": "2027-10-19",
            "years": 1,
            "renewal": 3.51,
            "auto_renew": true,
            "registrar": "example",
            "customer_id": 15
        }
    ]
}

Try itLive

GET/domains/{id}

Get domain

One domain with current nameservers and transfer lock (live from the registrar).

domains:read 200

Parameters

idpath · integer · required
ID der Domain

Possible errors

404
not_found Domain nicht gefunden
curl -s "https://mam-jahn.de/mjapi.php/v1/domains/301" \
  -H "Authorization: Bearer $MJ_KEY"

Response · 200

{
    "id": 301,
    "domain": "mein-projekt.de",
    "status": "Active",
    "expires": "2027-10-19",
    "nameservers": [
        "ns1.example.net",
        "ns2.example.net"
    ],
    "locked": true
}

Try itLive

POST/domains

Register / transfer domain

Orders the domain and pays with credit. If credit is insufficient nothing is ordered.

domains:order 201

Parameters

domainBody · Text · required
Domain mit Endung
typeBody · Text
register (Standard) oder transfer
yearsBody · integer
1–10 Jahre, Standard 1
authcodeBody · Text
nur bei transfer
nameserversBody · object
2–5 Nameserver als Liste
customer_idBody · integer
nur Reseller: Endkunde

Possible errors

402
insufficient_credit Guthaben reicht nicht
409
not_available Domain nicht frei
422
not_offered Endung/Laufzeit nicht im Angebot
curl -s -X POST "https://mam-jahn.de/mjapi.php/v1/domains" \
  -H "Authorization: Bearer $MJ_KEY" \
  -H "Content-Type: application/json" \
  -d '{"domain":"mein-projekt.de","type":"register","years":1,"nameservers":["ns1.example.net","ns2.example.net"],"customer_id":15}'

Response · 201

{
    "order_id": 513,
    "domain_id": 301,
    "invoice_id": 1295,
    "total": 3.51,
    "payment": "paid",
    "customer_id": 15
}

Try itLive

POST/domains/{id}/nameservers

Change nameservers

Sets 2 to 5 nameservers at the registrar.

domains:manage 200

Parameters

idpath · integer · required
ID der Domain
nameserversBody · object · required
Liste der Nameserver

Possible errors

422
invalid_nameservers 2–5 gültige Nameserver
502
registrar_error Registrar lehnt ab
curl -s -X POST "https://mam-jahn.de/mjapi.php/v1/domains/301/nameservers" \
  -H "Authorization: Bearer $MJ_KEY" \
  -H "Content-Type: application/json" \
  -d '{"nameservers":["ns1.example.net","ns2.example.net"]}'

Response · 200

{
    "ok": true,
    "nameservers": [
        "ns1.example.net",
        "ns2.example.net"
    ]
}

Try itLive

POST/domains/{id}/authcode

Request auth code

Auth code for moving to another provider. Some registrars email it to the owner (emailed = true).

domains:manage 200

Parameters

idpath · integer · required
ID der Domain

Possible errors

502
registrar_error Registrar lehnt ab
curl -s -X POST "https://mam-jahn.de/mjapi.php/v1/domains/301/authcode" \
  -H "Authorization: Bearer $MJ_KEY"

Response · 200

{
    "authcode": "Xy7-…",
    "emailed": false
}

Try itLive

POST/domains/{id}/lock

Transfer lock

Turn the lock on or off (not every TLD supports a lock).

domains:manage 200

Parameters

idpath · integer · required
ID der Domain
lockedBody · boolean · required
true oder false

Possible errors

502
registrar_error Registrar lehnt ab
curl -s -X POST "https://mam-jahn.de/mjapi.php/v1/domains/301/lock" \
  -H "Authorization: Bearer $MJ_KEY" \
  -H "Content-Type: application/json" \
  -d '{"locked":"true"}'

Response · 200

{
    "ok": true,
    "locked": true
}

Try itLive

Reseller

Endkunden unter deinem Konto (White-Label), Zuordnung, Abrechnung je Endkunde.

GET/reseller

Reseller account

Discount, credit, warning threshold and number of end customers, services and domains.

reseller:manage 200

Possible errors

403
not_reseller Konto ist kein Reseller
curl -s "https://mam-jahn.de/mjapi.php/v1/reseller" \
  -H "Authorization: Bearer $MJ_KEY"

Response · 200

{
    "reseller": true,
    "group": "Reseller 15 %",
    "discount_percent": 15,
    "credit": 240.5,
    "currency": "EUR",
    "low_credit_warning": 20,
    "customers": 12,
    "max_customers": null,
    "services": 31,
    "domains": 18
}

Try itLive

GET/reseller/customers

List end customers

Your end customers with number of services and domains. Search with ?q=.

reseller:manage 200

Parameters

qQuery · Text
Suche in Name, Firma, Referenz, E-Mail

Possible errors

403
not_reseller Konto ist kein Reseller
curl -s "https://mam-jahn.de/mjapi.php/v1/reseller/customers" \
  -H "Authorization: Bearer $MJ_KEY"

Response · 200

{
    "customers": [
        {
            "id": 15,
            "ref": "K-1042",
            "name": "Max Muster",
            "company": "Muster GmbH",
            "email": "max@example.de",
            "note": "",
            "created": "2026-10-19",
            "services": 2,
            "domains": 1
        }
    ]
}

Try itLive

POST/reseller/customers

Create end customer

Creates an end customer under your account. They get no emails and no access with us.

reseller:manage 201

Parameters

nameBody · Text
Name (name oder company Pflicht)
companyBody · Text
Firma
refBody · Text
deine Kundennummer
emailBody · Text
E-Mail (nur für dich)
noteBody · Text
Notiz

Possible errors

422
missing_name name oder company fehlt
409
customer_limit Höchstzahl erreicht
curl -s -X POST "https://mam-jahn.de/mjapi.php/v1/reseller/customers" \
  -H "Authorization: Bearer $MJ_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Max Muster","company":"Muster GmbH","ref":"K-1042","email":"max@example.de"}'

Response · 201

{
    "id": 15,
    "ref": "K-1042",
    "name": "Max Muster",
    "company": "Muster GmbH",
    "email": "max@example.de",
    "note": "",
    "created": "2026-10-19"
}

Try itLive

GET/reseller/customers/{id}

Get end customer

One end customer with services, domains and monthly cost (your purchase price).

reseller:manage 200

Parameters

idpath · integer · required
ID des Endkunden

Possible errors

404
not_found Endkunde nicht gefunden
curl -s "https://mam-jahn.de/mjapi.php/v1/reseller/customers/15" \
  -H "Authorization: Bearer $MJ_KEY"

Response · 200

{
    "id": 15,
    "ref": "K-1042",
    "name": "Max Muster",
    "services": [
        {
            "id": 877,
            "product": "KVM S",
            "status": "Active",
            "monthly": 8.42
        }
    ],
    "domains": [
        {
            "id": 301,
            "domain": "mein-projekt.de",
            "status": "Active"
        }
    ],
    "monthly_cost": 8.71
}

Try itLive

POST/reseller/customers/{id}

Update end customer

Changes only the fields you send.

reseller:manage 200

Parameters

idpath · integer · required
ID des Endkunden
nameBody · Text
Name
companyBody · Text
Firma
refBody · Text
deine Kundennummer
emailBody · Text
E-Mail
noteBody · Text
Notiz

Possible errors

404
not_found Endkunde nicht gefunden
curl -s -X POST "https://mam-jahn.de/mjapi.php/v1/reseller/customers/15" \
  -H "Authorization: Bearer $MJ_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Max Muster","ref":"K-1042","note":"zahlt jährlich"}'

Response · 200

{
    "id": 15,
    "ref": "K-1042",
    "name": "Max Muster",
    "company": "",
    "email": "",
    "note": "zahlt jährlich",
    "created": "2026-10-19"
}

Try itLive

DELETE/reseller/customers/{id}

Delete end customer

Only without running services. Assignments of ended services are removed.

reseller:manage 200

Parameters

idpath · integer · required
ID des Endkunden

Possible errors

409
has_services hat noch laufende Verträge
curl -s -X DELETE "https://mam-jahn.de/mjapi.php/v1/reseller/customers/15" \
  -H "Authorization: Bearer $MJ_KEY"

Response · 200

{
    "ok": true
}

Try itLive

POST/reseller/assign

Assign service/domain

Assigns an existing service or domain to an end customer (customer_id 0 = remove).

reseller:manage 200

Parameters

customer_idBody · integer · required
Endkunde oder 0
service_idBody · integer
Vertrag (oder domain_id)
domain_idBody · integer
Domain (oder service_id)

Possible errors

422
invalid_target genau eins von service_id/domain_id
curl -s -X POST "https://mam-jahn.de/mjapi.php/v1/reseller/assign" \
  -H "Authorization: Bearer $MJ_KEY" \
  -H "Content-Type: application/json" \
  -d '{"customer_id":15,"service_id":877}'

Response · 200

{
    "ok": true,
    "customer_id": 15
}

Try itLive

GET/reseller/report

Billing per end customer

All running services and domains per end customer with your purchase price and monthly value – the basis for your own invoices.

reseller:manage 200

Possible errors

403
not_reseller Konto ist kein Reseller
curl -s "https://mam-jahn.de/mjapi.php/v1/reseller/report" \
  -H "Authorization: Bearer $MJ_KEY"

Response · 200

{
    "currency": "EUR",
    "monthly_total": 214.3,
    "discount_percent": 15,
    "customers": [
        {
            "customer_id": 15,
            "ref": "K-1042",
            "name": "Muster GmbH",
            "monthly_cost": 8.71,
            "items": [
                {
                    "type": "service",
                    "id": 877,
                    "name": "KVM S",
                    "hostname": "node1.example.de",
                    "amount": 8.42,
                    "billingcycle": "monthly",
                    "monthly": 8.42,
                    "next_due": "2026-11-19"
                }
            ]
        }
    ]
}

Try itLive