Currency

SDKs & CLI

Every Malapos API route is reachable from three SDKs and the CLI, all generated from the API spec (the backend's own code), so none of them falls behind the API reference:

Package Every route
JavaScript / TypeScript npm install @forjio/malapos client.api.<area><Action>()
Python pip install forjio-malapos client.api.<area>_<action>()
Go go get github.com/hachimi-cat/malapos-go client.API.<Area><Action>(ctx, …)
CLI npm install -g @forjio/malapos-cli malapos api <area> <action>

The SDKs authenticate with Authorization: Bearer <token>: an sk_live_… API key (created under API keys in the dashboard; it acts in the workspace it was created in) or a Huudis access token. Each reads MALAPOS_TOKEN (and MALAPOS_BASE_URL, default https://malapos.com) when no token is passed.

SDKs

JavaScript / TypeScript:

import { MalaposClient } from '@forjio/malapos';

const client = new MalaposClient({ token: process.env.MALAPOS_TOKEN });
const products = await client.api.productsList({ q: 'kopi' });
await client.api.salesVoid(saleId, { reason: 'wrong item' });

Python:

from forjio_malapos import MalaposClient

client = MalaposClient(token=os.environ["MALAPOS_TOKEN"])
products = client.api.products_list(q="kopi")
client.api.sales_void(sale_id, reason="wrong item")

Go:

import malapos "github.com/hachimi-cat/malapos-go"

c := malapos.New(malapos.Config{Token: os.Getenv("MALAPOS_TOKEN")})
products, err := c.API.ProductsList(ctx, &malapos.ProductsListArgs{Q: "kopi"})

Each call returns the response envelope's data and raises the SDK's error type (MalaposError / *malapos.Error) with the envelope's error.code, HTTP status and request id. List routes that page return their cursor and hasMore: on the returned array in JS (page.cursor), as a Page in Python (page.cursor, page.has_more), and through c.DoEnvelope in Go.

Receiving webhooks

Every delivery is signed Malapos-Signature: t=<unix>,v1=<hex> (see Webhooks). Verify it over the raw body with the endpoint's whsec_… secret — each SDK has a helper that checks the signature and a 5-minute timestamp window and returns the event (or throws / raises / returns an error with code INVALID_SIGNATURE):

import express from 'express';
import { verifyWebhook } from '@forjio/malapos';

app.post('/hooks/malapos', express.raw({ type: 'application/json' }), (req, res) => {
  const event = verifyWebhook({
    rawBody: req.body,
    signature: req.header('Malapos-Signature'),
    secret: process.env.MALAPOS_WEBHOOK_SECRET!,
  });
  if (event.type === 'malapos.sale.completed.v1') {
    // event.data — the sale; event.id — drop duplicates by it
  }
  res.sendStatus(204);
});
from forjio_malapos import verify_webhook

event = verify_webhook(request.get_data(), request.headers.get("Malapos-Signature"),
                       os.environ["MALAPOS_WEBHOOK_SECRET"])
body, _ := io.ReadAll(r.Body)
event, err := malapos.VerifyWebhook(body, r.Header.Get(malapos.SignatureHeader), secret, nil)

What was delivered — every attempt, its response, the next retry — is in the delivery log: client.api.webhookSubscriptionsDeliveries({ status: 'failed' }), and client.api.webhookSubscriptionsDeliveriesRetry(id) sends one again.

CLI

npm install -g @forjio/malapos-cli

Then sign in — with your Huudis account in the browser, or with an API key on a server or in CI:

malapos auth login                           # Huudis device flow
malapos auth login --api-key - < key.txt     # or an sk_live_… API key, read from stdin
malapos auth whoami

Either way the credential is saved to ~/.malapos/credentials (one section per profile, mirroring the AWS CLI's ~/.aws/credentials convention; readable only by you). A Huudis session refreshes itself.

Auth commands

Command What it does
malapos auth login Sign in via the OIDC device flow: the CLI prints a code and opens the browser; approve it there. --no-browser only prints the link.
malapos auth login --api-key <key> Save an sk_live_… API key (created under API keys in the dashboard) to the profile instead. Pass - as the key to read it from stdin, so it stays out of your shell history.
malapos auth whoami Show what the CLI is signed in as: the Huudis user, or which key
malapos auth logout Remove the active profile (session or key) from ~/.malapos/credentials

Use --profile <name> to keep several sign-ins side by side (for example malapos --profile ci auth login --api-key -). The MALAPOS_TOKEN environment variable — an API key or a Huudis access token — wins over any saved profile, so CI can skip auth login entirely:

export MALAPOS_TOKEN=sk_live_…
malapos outlets list

Every route: malapos api

malapos api <area> <action> has a command for every API route, with flags typed from the API spec (malapos api --help lists the areas, malapos api products --help their actions):

malapos api products list --q kopi
malapos api sales void <saleId> --reason "wrong item"

Resource commands

The hand-written resource commands are read-only listers:

malapos outlets list      # store locations in your workspace
malapos products list     # products (with variants) in your workspace

malapos products list takes filters:

malapos products list --category <id> --active true --q kopi

Global flags

Every subcommand accepts:

Flag What it does
--json Machine-readable JSON output
--profile <name> Pick a credential profile in ~/.malapos/credentials
--base-url <url> Override the API base URL
--no-color Disable ANSI colors

Configuration

The CLI talks to https://malapos.com by default. Override it with the MALAPOS_BASE_URL environment variable (useful for staging):

MALAPOS_BASE_URL=https://staging-malapos.forjio.com malapos outlets list

Two more environment variables tune the device-flow login: MALAPOS_HUUDIS_ISSUER (default https://huudis.com) and MALAPOS_CLI_CLIENT_ID (default malapos-cli); auth login also takes them as --issuer <url> and --client-id <id>.

Programmatic access (REST)

Any HTTP client works too: send the token as Authorization: Bearer ….

curl https://malapos.com/api/v1/outlets \
  -H "Authorization: Bearer $MALAPOS_TOKEN"

Responses are the Forjio envelope { data, error, meta }. Every route, its parameters and body fields: API reference.

CurrencyRupiah is paid by QRIS, virtual account, e-wallet or card; US dollars settle through PayPal.