Articles

The price list (artikelregister) invoices are built from: what you sell, its price in öre, its VAT rate, its BAS account and whether it can carry a ROT/RUT deduction. Adding an article to an invoice line copies those onto the line, so changing an article later never changes an invoice already written.

The article number is the key bookkeepers use. It is unique in the organization and stays reserved by a deleted article, so to keep a price list in step with an ERP, look the article up by number (GET /articles?q=) and update it, or create it when it is missing.

List articles

GET/articles

Articles in article-number order, the order of a printed price list. Deleted articles are not listed; deactivated ones are, unless you filter on filter[active]=true.

q is a case-insensitive contains match on the name and the article number, so 1042 finds ART-1042.

Paging is by cursor: pass meta.next_cursor back as cursor together with the same filters and limit — the URLs in links do not carry your filters.

curl 'https://api.closepact.com/v1/api/articles' \
  -H "Authorization: Bearer $CLOSEPACT_API_KEY"
Response · 200
{
  "data": [
    {
      "id": "01a159f8-2d6a-7b3e-9f1c-8e4a2d7b5c63",
      "article_number": "ST-100",
      "name": "Hemstädning",
      "description": "Städning i hemmet enligt checklista. RUT-berättigad.",
      "type": "hour",
      "unit": "tim",
      "pricing": {
        "unit_price_cents": 45000,
        "currency": "SEK",
        "vat_rate": 25
      },
      "account_code": "3001",
      "rot_rut_eligible": true,
      "deductible": true,
      "line_type": "labour",
      "is_active": true,
      "metadata": [],
      "created_at": "2026-09-01T07:30:00+00:00",
      "updated_at": "2026-09-01T07:30:00+00:00",
      "deleted_at": null
    },
    {
      "id": "01a159f8-2d84-7c51-a2e6-3f9b1d8c4e70",
      "article_number": "ST-210",
      "name": "Trappstädning, per uppgång",
      "description": null,
      "type": "service",
      "unit": "st",
      "pricing": {
        "unit_price_cents": 95000,
        "currency": "SEK",
        "vat_rate": 25
      },
      "account_code": "3001",
      "rot_rut_eligible": false,
      "deductible": false,
      "line_type": "service",
      "is_active": true,
      "metadata": [],
      "created_at": "2026-09-01T07:31:12+00:00",
      "updated_at": "2026-09-01T07:31:12+00:00",
      "deleted_at": null
    }
  ],
  "links": {
    "first": null,
    "last": null,
    "prev": null,
    "next": null
  },
  "meta": {
    "path": "https://api.closepact.com/v1/api/articles",
    "per_page": 50,
    "next_cursor": null,
    "prev_cursor": null
  }
}

Query parameters

  • qstring

    Search the name and the article number.

    Example städ

  • filter[type]string | array of strings

    One type, or several as filter[type][]=hour&filter[type][]=service.

  • filter[active]boolean

    true for articles that can be picked for new lines, false for deactivated ones.

  • filter[rot_rut_eligible]boolean

    Only articles that can, or cannot, carry a ROT/RUT deduction.

  • filter[account_code]string

    Only articles booked to this BAS account.

    Example 3001

  • limitinteger

    Articles per page.

    Default 501–100

  • cursorstring

    Opaque cursor from meta.next_cursor or meta.prev_cursor of the previous page.

Responses

  • Headers

    • X-RateLimit-Limit — Requests this key may make per minute.
    • X-RateLimit-Remaining — Requests left in the current minute.
    • dataarray of objectsrequired
      • idstring(uuid)required
      • article_numberstringrequired

        Artikelnummer, unique in the organization.

      • namestringrequired

        Becomes the line's description.

      • descriptionstringnullablerequired
      • typestringrequired

        One ofgoodsservicehourfee

      • unitstringnullablerequired

        e.g. tim, st, kvm.

      • pricingobjectrequired
      • account_codestringnullablerequired

        BAS sales account.

      • rot_rut_eligiblebooleanrequired

        Only ever true for hour and service articles.

      • deductiblebooleanrequired

        Whether a line built from it counts towards a ROT/RUT deduction: eligible and labour. The field to rely on.

      • line_typestringrequired

        What an invoice line built from it becomes.

        One ofgoodsservicelabourfee

      • is_activebooleanrequired

        False once deactivated; still resolvable, no longer offered.

      • metadataobject | array of valuesnullablerequired

        Free-form; an empty list when unused.

      • created_atstring(date-time)nullablerequired
      • updated_atstring(date-time)nullablerequired
      • deleted_atstring(date-time)nullablerequired
    • linksobjectrequired
    • metaobjectrequired
  • 401No key, or the key is invalid, revoked or expired, or its creator no longer has access.
    Errors
  • 402The organization has not bought the module this endpoint belongs to, or it has lapsed to read-only, or its tier does not include what the operation needs: feature names the capability (the operation's x-feature) and required_tier the cheapest tier that grants it. Every operation answers this with "feature": "core.api" when no module the organization holds is on a tier that includes the API.
    Errors
  • 403The key lacks the scope, or the member it acts as lacks the permission or holds no seat in the module (module_seat_required — an administrator assigns seats under Settings → Users), or the organization is suspended.
    Errors
  • 429The key has made more requests this minute than its limit allows.
    Errors

Create an article

POST/articles
Scope write Module Invoicing Permission invoicing.articles.manage

Adds an article to the price list. article_number and name are required; the rest defaults to a 25 % goods article priced at 0 kr in SEK.

  • Price is unit_price_cents, a whole number of öre excluding VAT: 450,00 kr is 45000. A decimal is refused, because it is almost always kronor sent by mistake.
  • VAT must be 25, 12, 6 or 0; anything else is a 422 that names the four rates.
  • Type decides what a line built from the article becomes: hour → labour, service → service, fee → fee, goods → goods.
  • ROT/RUT. rot_rut_eligible is kept only for hour and service articles — ROT and RUT cover work, never materials — and it is cleared whenever the type stops qualifying. deductible in the response is the answer to rely on.
  • Account is the BAS sales account, e.g. 3001. Left empty, a line built from the article gets the standard account for its VAT rate (3001, 3002, 3003).

An article number that is already taken — also by a deleted article — answers 409 naming the article that holds it.

curl -X POST 'https://api.closepact.com/v1/api/articles' \
  -H "Authorization: Bearer $CLOSEPACT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "article_number": "ST-100",
  "name": "Hemstädning",
  "description": "Städning i hemmet enligt checklista. RUT-berättigad.",
  "type": "hour",
  "unit": "tim",
  "unit_price_cents": 45000,
  "vat_rate": 25,
  "account_code": "3001",
  "rot_rut_eligible": true
}'
Response · 201
{
  "data": {
    "id": "01a159f8-2d6a-7b3e-9f1c-8e4a2d7b5c63",
    "article_number": "ST-100",
    "name": "Hemstädning",
    "description": "Städning i hemmet enligt checklista. RUT-berättigad.",
    "type": "hour",
    "unit": "tim",
    "pricing": {
      "unit_price_cents": 45000,
      "currency": "SEK",
      "vat_rate": 25
    },
    "account_code": "3001",
    "rot_rut_eligible": true,
    "deductible": true,
    "line_type": "labour",
    "is_active": true,
    "metadata": [],
    "created_at": "2026-10-18T09:00:00+00:00",
    "updated_at": "2026-10-18T09:00:00+00:00",
    "deleted_at": null
  }
}

Request body

application/json · required

The writable fields of an article. On update every field is optional.

  • article_numberstringrequired

    at most 32 characters

  • namestringrequired

    at most 200 characters

  • descriptionstringnullable

    at most 2,000 characters

  • typestring

    One ofgoodsservicehourfee

    Default "goods"

  • unitstringnullable

    at most 32 characters

  • unit_price_centsinteger

    Öre, excluding VAT.

    Default 0≥ 0

  • currencystring

    Default "SEK"exactly 3 characters

  • vat_ratenumber

    One of251260

    Default 25

  • account_codestringnullable

    at most 8 characters

  • rot_rut_eligibleboolean

    Kept only for hour and service articles.

    Default false

  • is_activeboolean

    Default true

  • sub_entity_idstring(uuid)nullable
  • metadataobject

Responses

  • Headers

    • X-RateLimit-Limit — Requests this key may make per minute.
    • X-RateLimit-Remaining — Requests left in the current minute.
    • dataobjectrequired

      An article in the price list.

      • idstring(uuid)required
      • article_numberstringrequired

        Artikelnummer, unique in the organization.

      • namestringrequired

        Becomes the line's description.

      • descriptionstringnullablerequired
      • typestringrequired

        One ofgoodsservicehourfee

      • unitstringnullablerequired

        e.g. tim, st, kvm.

      • pricingobjectrequired
      • account_codestringnullablerequired

        BAS sales account.

      • rot_rut_eligiblebooleanrequired

        Only ever true for hour and service articles.

      • deductiblebooleanrequired

        Whether a line built from it counts towards a ROT/RUT deduction: eligible and labour. The field to rely on.

      • line_typestringrequired

        What an invoice line built from it becomes.

        One ofgoodsservicelabourfee

      • is_activebooleanrequired

        False once deactivated; still resolvable, no longer offered.

      • metadataobject | array of valuesnullablerequired

        Free-form; an empty list when unused.

      • created_atstring(date-time)nullablerequired
      • updated_atstring(date-time)nullablerequired
      • deleted_atstring(date-time)nullablerequired
  • 401No key, or the key is invalid, revoked or expired, or its creator no longer has access.
    Errors
  • 402The organization has not bought the module this endpoint belongs to, or it has lapsed to read-only, or its tier does not include what the operation needs: feature names the capability (the operation's x-feature) and required_tier the cheapest tier that grants it. Every operation answers this with "feature": "core.api" when no module the organization holds is on a tier that includes the API.
    Errors
  • 403The key lacks the scope, or the member it acts as lacks the permission or holds no seat in the module (module_seat_required — an administrator assigns seats under Settings → Users), or the organization is suspended.
    Errors
  • 409Another article — possibly a deleted one — already has this article number. error is conflict; the message names the article that holds the number.
    Errors
  • 422The request body or query failed validation.
    Errors
  • 429The key has made more requests this minute than its limit allows.
    Errors

Get an article

GET/articles/{article}

One article. A deleted article answers 404, like another organization's.

curl 'https://api.closepact.com/v1/api/articles/01a14f2c-7c1e-7d0b-9a3e-3f5b2c8d1e40' \
  -H "Authorization: Bearer $CLOSEPACT_API_KEY"
Response · 200
{
  "data": {
    "id": "01a14f2c-7c1e-7d0b-9a3e-3f5b2c8d1e40",
    "article_number": "string",
    "name": "Anna Lindqvist",
    "description": "A short description.",
    "type": "goods",
    "unit": "string",
    "pricing": {
      "unit_price_cents": 125000,
      "currency": "SEK",
      "vat_rate": 25
    },
    "account_code": "string",
    "rot_rut_eligible": true,
    "deductible": true,
    "line_type": "goods",
    "is_active": true,
    "metadata": {},
    "created_at": "2026-10-18T09:30:00Z",
    "updated_at": "2026-10-18T09:30:00Z",
    "deleted_at": "2026-10-18T09:30:00Z"
  }
}

Path parameters

  • articlestring(uuid)required

    The article's id.

Responses

  • Headers

    • X-RateLimit-Limit — Requests this key may make per minute.
    • X-RateLimit-Remaining — Requests left in the current minute.
    • dataobjectrequired

      An article in the price list.

      • idstring(uuid)required
      • article_numberstringrequired

        Artikelnummer, unique in the organization.

      • namestringrequired

        Becomes the line's description.

      • descriptionstringnullablerequired
      • typestringrequired

        One ofgoodsservicehourfee

      • unitstringnullablerequired

        e.g. tim, st, kvm.

      • pricingobjectrequired
      • account_codestringnullablerequired

        BAS sales account.

      • rot_rut_eligiblebooleanrequired

        Only ever true for hour and service articles.

      • deductiblebooleanrequired

        Whether a line built from it counts towards a ROT/RUT deduction: eligible and labour. The field to rely on.

      • line_typestringrequired

        What an invoice line built from it becomes.

        One ofgoodsservicelabourfee

      • is_activebooleanrequired

        False once deactivated; still resolvable, no longer offered.

      • metadataobject | array of valuesnullablerequired

        Free-form; an empty list when unused.

      • created_atstring(date-time)nullablerequired
      • updated_atstring(date-time)nullablerequired
      • deleted_atstring(date-time)nullablerequired
  • 401No key, or the key is invalid, revoked or expired, or its creator no longer has access.
    Errors
  • 402The organization has not bought the module this endpoint belongs to, or it has lapsed to read-only, or its tier does not include what the operation needs: feature names the capability (the operation's x-feature) and required_tier the cheapest tier that grants it. Every operation answers this with "feature": "core.api" when no module the organization holds is on a tier that includes the API.
    Errors
  • 403The key lacks the scope, or the member it acts as lacks the permission or holds no seat in the module (module_seat_required — an administrator assigns seats under Settings → Users), or the organization is suspended.
    Errors
  • 404No such record in this organization.
    Errors
  • 429The key has made more requests this minute than its limit allows.
    Errors

Update an article

PATCH/articles/{article}
Scope write Module Invoicing Permission invoicing.articles.manage

Changes only the fields you send. A new price applies to lines added from now on; existing invoice lines keep the price they were given. ROT/RUT eligibility is re-derived on every update, so changing an hour article to goods takes the deduction off it. Renumbering to a number that is taken answers 409.

curl -X PATCH 'https://api.closepact.com/v1/api/articles/01a14f2c-7c1e-7d0b-9a3e-3f5b2c8d1e40' \
  -H "Authorization: Bearer $CLOSEPACT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "unit_price_cents": 47500
}'
Response · 200
{
  "data": {
    "id": "01a14f2c-7c1e-7d0b-9a3e-3f5b2c8d1e40",
    "article_number": "string",
    "name": "Anna Lindqvist",
    "description": "A short description.",
    "type": "goods",
    "unit": "string",
    "pricing": {
      "unit_price_cents": 125000,
      "currency": "SEK",
      "vat_rate": 25
    },
    "account_code": "string",
    "rot_rut_eligible": true,
    "deductible": true,
    "line_type": "goods",
    "is_active": true,
    "metadata": {},
    "created_at": "2026-10-18T09:30:00Z",
    "updated_at": "2026-10-18T09:30:00Z",
    "deleted_at": "2026-10-18T09:30:00Z"
  }
}

Path parameters

  • articlestring(uuid)required

    The article's id.

Request body

application/json · required

The writable fields of an article. On update every field is optional.

  • article_numberstring

    at most 32 characters

  • namestring

    at most 200 characters

  • descriptionstringnullable

    at most 2,000 characters

  • typestring

    One ofgoodsservicehourfee

    Default "goods"

  • unitstringnullable

    at most 32 characters

  • unit_price_centsinteger

    Öre, excluding VAT.

    Default 0≥ 0

  • currencystring

    Default "SEK"exactly 3 characters

  • vat_ratenumber

    One of251260

    Default 25

  • account_codestringnullable

    at most 8 characters

  • rot_rut_eligibleboolean

    Kept only for hour and service articles.

    Default false

  • is_activeboolean

    Default true

  • sub_entity_idstring(uuid)nullable
  • metadataobject

Responses

  • Headers

    • X-RateLimit-Limit — Requests this key may make per minute.
    • X-RateLimit-Remaining — Requests left in the current minute.
    • dataobjectrequired

      An article in the price list.

      • idstring(uuid)required
      • article_numberstringrequired

        Artikelnummer, unique in the organization.

      • namestringrequired

        Becomes the line's description.

      • descriptionstringnullablerequired
      • typestringrequired

        One ofgoodsservicehourfee

      • unitstringnullablerequired

        e.g. tim, st, kvm.

      • pricingobjectrequired
      • account_codestringnullablerequired

        BAS sales account.

      • rot_rut_eligiblebooleanrequired

        Only ever true for hour and service articles.

      • deductiblebooleanrequired

        Whether a line built from it counts towards a ROT/RUT deduction: eligible and labour. The field to rely on.

      • line_typestringrequired

        What an invoice line built from it becomes.

        One ofgoodsservicelabourfee

      • is_activebooleanrequired

        False once deactivated; still resolvable, no longer offered.

      • metadataobject | array of valuesnullablerequired

        Free-form; an empty list when unused.

      • created_atstring(date-time)nullablerequired
      • updated_atstring(date-time)nullablerequired
      • deleted_atstring(date-time)nullablerequired
  • 401No key, or the key is invalid, revoked or expired, or its creator no longer has access.
    Errors
  • 402The organization has not bought the module this endpoint belongs to, or it has lapsed to read-only, or its tier does not include what the operation needs: feature names the capability (the operation's x-feature) and required_tier the cheapest tier that grants it. Every operation answers this with "feature": "core.api" when no module the organization holds is on a tier that includes the API.
    Errors
  • 403The key lacks the scope, or the member it acts as lacks the permission or holds no seat in the module (module_seat_required — an administrator assigns seats under Settings → Users), or the organization is suspended.
    Errors
  • 404No such record in this organization.
    Errors
  • 409Another article — possibly a deleted one — already has this article number. error is conflict; the message names the article that holds the number.
    Errors
  • 422The request body or query failed validation.
    Errors
  • 429The key has made more requests this minute than its limit allows.
    Errors

Delete an article

DELETE/articles/{article}
Scope write Module Invoicing Permission invoicing.articles.manage

Removes the article — unless it appears on an issued invoice. Those have to be reproducible for seven years, so such an article is deactivated instead: it stays resolvable from the invoice lines and disappears from the articles people pick from. The response says which of the two happened and why.

Either way its number stays reserved. Drafts do not count; a draft can still be changed.

curl -X DELETE 'https://api.closepact.com/v1/api/articles/01a14f2c-7c1e-7d0b-9a3e-3f5b2c8d1e40' \
  -H "Authorization: Bearer $CLOSEPACT_API_KEY"
Response
{
  "data": {
    "deleted": true,
    "deactivated": false,
    "issued_invoice_lines": 0,
    "reason": null
  }
}

Path parameters

  • articlestring(uuid)required

    The article's id.

Responses

  • Headers

    • X-RateLimit-Limit — Requests this key may make per minute.
    • X-RateLimit-Remaining — Requests left in the current minute.
    • dataobjectrequired
      • deletedbooleanrequired
      • deactivatedbooleanrequired

        True when the article was kept and deactivated instead.

      • issued_invoice_linesintegerrequired

        How many issued invoice lines use it.

      • reasonstringnullablerequired
  • 401No key, or the key is invalid, revoked or expired, or its creator no longer has access.
    Errors
  • 402The organization has not bought the module this endpoint belongs to, or it has lapsed to read-only, or its tier does not include what the operation needs: feature names the capability (the operation's x-feature) and required_tier the cheapest tier that grants it. Every operation answers this with "feature": "core.api" when no module the organization holds is on a tier that includes the API.
    Errors
  • 403The key lacks the scope, or the member it acts as lacks the permission or holds no seat in the module (module_seat_required — an administrator assigns seats under Settings → Users), or the organization is suspended.
    Errors
  • 404No such record in this organization.
    Errors
  • 429The key has made more requests this minute than its limit allows.
    Errors