Skip to content

Resources

Invoicing

A service company's invoice basis, made when a technician approves a service report from speech, and its catalogue. The fields are the same as in the CSV and Excel export, so an accounting system is set up once. When the company sets a webhook address in the app, each approved basis is posted to it as invoice_draft.approved, with the body signed in the header X-Maci-Signature as sha256= and the HMAC-SHA256 of the body with the webhook's secret.

Webhook: invoice_draft.approved is posted to your own address as it happens. See webhooks.

The invoice draft model

Properties

  • id string (uuid)
  • status string

    One of draft, approved

  • service_report_id string (uuid)
  • unit_id string (uuid)
  • unit_public_id string, nullable
  • unit string, nullable
  • customer object
  • visit_date string (date)
  • technician string, nullable
  • currency string
  • total_excl_vat number
  • approved_at string (date-time), nullable
  • exported_at string (date-time), nullable
  • lines array

The price list item model

Properties

  • id string (uuid)
  • item_number string
  • description string
  • unit_of_measure string
  • price_excl_vat number
  • kind string

    One of part, refrigerant, labour, travel, other

  • active boolean
  • updated_at string (date-time), nullable

GET/invoice-drafts

List invoice bases

The organisation's invoice basis.

For an accounting system: status=approved&exported=false gives what is ready to invoice and not yet taken.

Scope: invoices:read

Query parameters

  • status string

    One of draft, approved

  • exported boolean

    false for only those not marked exported, true for only those marked.

  • since string (date-time)

    Only those changed at or after this time.

  • limit integer

    Records per page. At most 100, default 50.

  • cursor string

    The value of next_cursor from the page before.

Response

200 A page of invoice bases with their lines. The fields are those of the invoice draft model.

Request
GET/invoice-drafts
curl https://api.maci.energy/v1/invoice-drafts \
  -H "Authorization: Bearer $MACI_API_KEY"
Response 200
{
  "data": [
    {
      "id": "3c8d2a71-6e0b-4f95-a2d4-8b1e7c5f0a93",
      "status": "draft",
      "service_report_id": "9a4f0e2b-7c13-4d68-b5e1-2d9c6a3f8b07",
      "unit_id": "0b6f4c1e-5a1d-4a57-9f0e-2f6f3f0c9a11",
      "unit_public_id": "MC-0482",
      "unit": "Cold room 2",
      "customer": {
        "name": "Cold room 2",
        "cvr": "Cvr",
        "vat_number": null
      },
      "visit_date": "2026-10-30",
      "technician": "Jonas L.",
      "currency": "DKK",
      "total_excl_vat": 1890,
      "approved_at": "2026-10-30T09:15:00Z",
      "exported_at": null,
      "lines": [
        {
          "type": "part",
          "item_number": "1000",
          "description": "Labour",
          "quantity": 1,
          "unit_of_measure": "hours",
          "unit_price": 700,
          "amount_excl_vat": 1050,
          "source": "speech",
          "match_sure": true
        }
      ]
    }
  ],
  "next_cursor": null
}

POST/invoice-drafts/mark-exported

Mark invoice bases exported

Mark invoice bases exported.

Only approved ones are marked, and only the first time; calling it again with the same IDs is no error.

Scope: invoices:write

Body

  • ids array required

Response

200 How many were marked now, the bases as they are, and the IDs not found. The fields are those of the invoice draft model.

Request
POST/invoice-drafts/mark-exported
curl -X POST https://api.maci.energy/v1/invoice-drafts/mark-exported \
  -H "Authorization: Bearer $MACI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "ids": [
      "3c8d2a71-6e0b-4f95-a2d4-8b1e7c5f0a93"
    ]
  }'
Response 200
{
  "marked": 1,
  "data": [
    {
      "id": "3c8d2a71-6e0b-4f95-a2d4-8b1e7c5f0a93",
      "status": "draft",
      "service_report_id": "9a4f0e2b-7c13-4d68-b5e1-2d9c6a3f8b07",
      "unit_id": "0b6f4c1e-5a1d-4a57-9f0e-2f6f3f0c9a11",
      "unit_public_id": "MC-0482",
      "unit": "Cold room 2",
      "customer": {
        "name": "Cold room 2",
        "cvr": "Cvr",
        "vat_number": null
      },
      "visit_date": "2026-10-30",
      "technician": "Jonas L.",
      "currency": "DKK",
      "total_excl_vat": 1890,
      "approved_at": "2026-10-30T09:15:00Z",
      "exported_at": null,
      "lines": [
        {
          "type": "part",
          "item_number": "1000",
          "description": "Labour",
          "quantity": 1,
          "unit_of_measure": "hours",
          "unit_price": 700,
          "amount_excl_vat": 1050,
          "source": "speech",
          "match_sure": true
        }
      ]
    }
  ],
  "not_found": [
    "9bcd14b2-18ed-41bf-a2d2-1978a263be9d"
  ]
}

GET/invoice-drafts/{draft}

Get an invoice basis

One invoice basis with all its lines and sources.

Scope: invoices:read

Path parameters

  • draft string (uuid) required

    The ID of the invoice basis.

Response

200 The invoice basis. The fields are those of the invoice draft model.

Request
GET/invoice-drafts/{draft}
curl https://api.maci.energy/v1/invoice-drafts/3c8d2a71-6e0b-4f95-a2d4-8b1e7c5f0a93 \
  -H "Authorization: Bearer $MACI_API_KEY"
Response 200
{
  "id": "3c8d2a71-6e0b-4f95-a2d4-8b1e7c5f0a93",
  "status": "draft",
  "service_report_id": "9a4f0e2b-7c13-4d68-b5e1-2d9c6a3f8b07",
  "unit_id": "0b6f4c1e-5a1d-4a57-9f0e-2f6f3f0c9a11",
  "unit_public_id": "MC-0482",
  "unit": "Cold room 2",
  "customer": {
    "name": "Cold room 2",
    "cvr": "Cvr",
    "vat_number": null
  },
  "visit_date": "2026-10-30",
  "technician": "Jonas L.",
  "currency": "DKK",
  "total_excl_vat": 1890,
  "approved_at": "2026-10-30T09:15:00Z",
  "exported_at": null,
  "lines": [
    {
      "type": "part",
      "item_number": "1000",
      "description": "Labour",
      "quantity": 1,
      "unit_of_measure": "hours",
      "unit_price": 700,
      "amount_excl_vat": 1050,
      "source": "speech",
      "match_sure": true
    }
  ]
}

GET/price-list-items

List price list items

The organisation's catalogue.

Scope: price-list:read

Query parameters

  • limit integer

    Records per page. At most 100, default 50.

  • cursor string

    The value of next_cursor from the page before.

Response

200 A page of items. The fields are those of the price list item model.

Request
GET/price-list-items
curl https://api.maci.energy/v1/price-list-items \
  -H "Authorization: Bearer $MACI_API_KEY"
Response 200
{
  "data": [
    {
      "id": "f6ec47fe-e08d-464d-aba0-eaf6b286a073",
      "item_number": "1000",
      "description": "Labour",
      "unit_of_measure": "hours",
      "price_excl_vat": 700,
      "kind": "part",
      "active": true,
      "updated_at": "2026-10-30T09:15:00Z"
    }
  ],
  "next_cursor": null
}

PUT/price-list-items

Save price list items

Create or update items from the accounting system.

Each item is found by its item number, whatever its case or punctuation, and created when it is new.

Scope: price-list:write

Body

  • items array required

Response

200 How many were created, updated and skipped.

Request
PUT/price-list-items
curl -X PUT https://api.maci.energy/v1/price-list-items \
  -H "Authorization: Bearer $MACI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      {
        "item_number": "1000",
        "description": "Labour",
        "unit_of_measure": "hours",
        "price_excl_vat": 700,
        "kind": "part",
        "active": true
      }
    ]
  }'
Response 200
{
  "created": 1,
  "updated": 1,
  "skipped": 1
}