Download OpenAPI specification:
OAuth2 agent surface for Konto — customers, items, invoices, costs, projects, tasks and product sales.
The Agent API lets a third-party application act on behalf of a Konto user, after that user signs in and consents to a set of scopes. It is the OAuth2 surface behind the Konto MCP connector and is the recommended path for user-delegated and AI integrations.
For headless server-to-server integrations (no user to log in) — e.g. a billing cron or an ERP sync running as a service — use the legacy
username+api_keyREST API instead (see the in-app reference).
| Host | Purpose | |
|---|---|---|
| Production | https://konto.is |
Real accounts, real invoices & email. |
| Development | https://dev.konto.is |
Safe sandbox. Sign in with a dev/test account. |
OAuth clients are per-environment: a client_id registered on dev does
not exist on prod, and vice versa. The OAuth endpoints live under
/strax/agent/*; the resource endpoints under /api/v1/agent/*.
dev.konto.is is always in maintenance mode. Server-side calls to dev must append
?en4_maint_code=<code>or receive HTTP 503. Ask Konto for the current dev bypass code. Never send it to production.
Every resource endpoint returns a JSON envelope:
{ "status": true, "message": "", "result": { ... } }
status is a boolean. On a handled error the HTTP status may still be 200
with status: false and a message — always check status, not just the
HTTP code. (Auth, scope and method failures do use real 4xx codes, with the
Error body { "error": true, "message": "…", "code": 403 }.)
A plan that lacks the feature behind an endpoint is also a handled error:
HTTP 200, status: false, "Subscription does not include the required
feature: …".
Most creates and updates answer with result = the record's guid, not the
record. GET it afterwards if you need the stored values.
Create/update endpoints read the resource object from a data field. Send
it as a JSON-encoded string — this is the universally-supported form and
the one the official MCP/SDK uses:
{ "data": "{\"name\":\"Acme ehf\",\"kennitala\":\"1234567890\",\"email\":\"acme@example.is\",\"lang\":\"is\",\"currency\":\"ISK\"}" }
With an application/json body, data may also be the object itself
({"data":{...}}). Customer endpoints additionally accept the fields flat at
the top level. The schemas below document the decoded object shape in each
data field. Endpoints marked otherwise (costs, task time entries) take
top-level fields.
Unless an endpoint says otherwise, a list without limit returns every
match in one response. The exceptions: GET /costs returns 10 per page by
default, and the product-sale lists always page (10 per page by default).
Projects, time entries and the sync mode (updated_since / cursor) have
their own paging rules, described on those endpoints.
Every write (anything that is not a GET) accepts an optional
Idempotency-Key header. A retry with the same key and the same request
replays the first response instead of writing again — use it on invoice
creation so a network retry cannot issue the invoice twice.
tax): S = 24 %, AA = 11 %, Z = 0 %.uom): C62 pieces · HUR hours · DAY days ·
KGS kg · MTR m · LTR l · MTK m² · MTQ m³ · TNE t · KWH kWh ·
MIN minutes · KTM km.amount must equal Σ(line items) + VAT, rounded to 2 dp — the
server rejects a mismatch.issue_date is today or earlier, and
due_date ≤ settlement_date. All three are required; settlement_date
is the eindagi.guid needs item_number, description, qty, uom and tax.kennitala: 10 digits, no dash; validated (mod-11 checksum).trading_partner_id (e-invoice): the recipient's bare kennitala —
do not prefix the Peppol scheme 0196:.how_paid: 1 Account · 2 Debit card · 3 Credit card · 4 Owner cash.output_select (delivery): 2 e-invoice/XML (needs
trading_partner_id) · 3 email · 4 PDF.Exchange an authorization code (with grant_type=authorization_code) or
a refresh_token (with grant_type=refresh_token) for an access token.
Refresh tokens rotate — persist the new refresh_token from every
response. Refresh does not require redirect_uri.
| client_id required | string |
| client_secret | string Required for confidential clients. |
| grant_type required | string Enum: "authorization_code" "refresh_token" |
| code | string Required when grant_type=authorization_code. |
| redirect_uri | string <uri> Required (and exact-match) when exchanging a code. |
| code_verifier | string PKCE verifier, if a challenge was sent. |
| refresh_token | string Required when grant_type=refresh_token. |
{- "client_id": "string",
- "client_secret": "string",
- "grant_type": "authorization_code",
- "code": "string",
- "code_verifier": "string",
- "refresh_token": "string"
}{- "access_token": "string",
- "refresh_token": "string",
- "expires_in": 0,
- "scope": "string"
}Create an agent client and receive a client_id + client_secret
(the secret is shown once). In practice Konto often provisions
clients — especially shared app clients (one client many merchants
authorize) — manually; contact Konto for onboarding.
| name required | string |
| description | string |
| redirect_uri required | string <uri> Exact-match at authorize time. |
{- "name": "string",
- "description": "string",
}{- "client_id": "string",
- "client_secret": "string"
}Returns the connected company name, registration number (kennitala) and username. A plain object, not the status/result envelope.
{- "company_name": "string",
- "registration_no": "string",
- "username": "string"
}The agent clients currently authorized on this account, with granted scopes. A plain object, not the status/result envelope.
{- "data": [
- {
- "agent_id": "string",
- "name": "string",
- "scopes": [
- "string"
], - "granted_at": "2026-10-01 09:30:00"
}
], - "total": 0
}Immediately invalidates that client's tokens. Irreversible. Revoking the client you are currently using cuts off your own access.
| id required | string The agent client_id to revoke. |
{- "message": "Agent access revoked",
- "agent_id": "string"
}Recent actions taken by agent clients on this account, newest first. A plain object, not the status/result envelope.
| agent_id | string Only this client's actions. It must have an active grant on the account, or HTTP 403. |
| limit | integer [ 1 .. 200 ] Default: 50 Results per page, 1–200. |
| page | integer Default: 1 Page number (default 1). |
{- "data": [
- {
- "agent_id": "string",
- "action": "string",
- "ip_address": "string",
- "timestamp": "2026-10-01 09:30:00"
}
], - "total": 0,
- "page": 0,
- "limit": 0
}Results include deactivated profiles — filter client-side if needed.
Without limit, every customer is returned.
search matches the customer name only (substring). kennitala
switches to a kennitala search; it is a substring match too, so check
registration_no in the results when you need an exact hit.
| search | string Substring of the customer name. |
| kennitala | string Substring of the kennitala. When present, |
| limit | integer >= 1 Page size. Without it every match is returned in one response (there is no default page size). In sync mode default 100, max 500. |
| page | integer Default: 1 Page number (default 1). |
{- "status": true,
- "message": "string",
- "result": [
- {
- "guid": "5d1e2c4a-8b7f-11ef-9c3a-0242ac120002",
- "name": "Byggir ehf.",
- "registration_no": "4602070880",
- "email": "bokhald@byggir.is",
- "output_select": 3,
- "trading_partner_id": "",
- "address": "Lækjargata 4",
- "zip": "101",
- "city": "Reykjavík",
- "phone_number": "",
- "vat": "",
- "lang": "is",
- "currency": "ISK",
- "tax_exempt": 0,
- "term": "",
- "due_date": 3,
- "settlement_date": 7,
- "photo": "",
- "updated_timestamp": "2026-10-12"
}
]
}Does not dedupe by kennitala — each call creates a new profile. To
change an existing one, GET it then PUT. result is the new customer's
guid.
On create, output_select is not read: the customer gets email delivery
(3), or e-invoice (2) when trading_partner_id is sent. So email is
always required here. For a PDF-only customer (4), create it and then
PUT output_select: 4.
A refusal is HTTP 200 with status: false and one of: Please input validate kennitala, Name is required, Please input validate email,
Trading partner is required, Language is required, Currency is required, or Data customer invalidate (missing or unreadable data).
| Idempotency-Key | string [ 1 .. 128 ] characters Example: 7c1f0d2e-ops-4711 Optional on any write. A retry with the same key and the same request
(path and body) replays the stored response — same HTTP status, plus the
header |
The customer object, as a JSON-encoded data string (also accepts a nested object or flat top-level fields).
required | string or CustomerCreate (object) |
{- "name": "Acme ehf",
- "kennitala": "1234567890",
- "email": "acme@example.is",
- "lang": "is",
- "currency": "ISK"
}{- "status": true,
- "message": "string",
- "result": null
}| guid required | string The resource's GUID. |
{- "status": true,
- "message": "string",
- "result": {
- "guid": "5d1e2c4a-8b7f-11ef-9c3a-0242ac120002",
- "name": "Byggir ehf.",
- "registration_no": "4602070880",
- "email": "bokhald@byggir.is",
- "output_select": 3,
- "trading_partner_id": "",
- "address": "Lækjargata 4",
- "zip": "101",
- "city": "Reykjavík",
- "phone_number": "",
- "vat": "",
- "lang": "is",
- "currency": "ISK",
- "tax_exempt": 0,
- "term": "",
- "due_date": 3,
- "settlement_date": 7,
- "photo": "",
- "updated_timestamp": "2026-10-12"
}
}Send the fields you want to change; the others keep their values. The
whole record is then validated with the create rules, and here
output_select can be set (4 makes email optional). result is the
customer's guid. PUT bodies must be application/json.
| guid required | string The resource's GUID. |
| Idempotency-Key | string [ 1 .. 128 ] characters Example: 7c1f0d2e-ops-4711 Optional on any write. A retry with the same key and the same request
(path and body) replays the stored response — same HTTP status, plus the
header |
The customer object, as a JSON-encoded data string (also accepts a nested object or flat top-level fields).
required | string or CustomerCreate (object) |
{- "name": "Acme ehf",
- "kennitala": "1234567890",
- "email": "acme@example.is",
- "lang": "is",
- "currency": "ISK"
}{- "status": true,
- "message": "string",
- "result": "614669f6-3560-11e7-8d19-408d5c6208bc"
}Every catalogue item, inactive ones included. Without limit, all of them.
| limit | integer >= 1 Page size. Without it every match is returned in one response (there is no default page size). In sync mode default 100, max 500. |
| page | integer Default: 1 Page number (default 1). |
| with_lots | string Default: "0" Enum: "0" "1"
|
{- "status": true,
- "message": "string",
- "result": [
- {
- "guid": "43521ec8-3413-11e7-b148-408d5c6208bc",
- "item_number": "1024",
- "description": "Ráðgjöf",
- "uom": "HUR",
- "tax": "S",
- "unit_price": "15000",
- "category": "",
- "active": 1,
- "updated_timestamp": "2026-10-01",
- "qty": 0,
- "qty_available": 0,
- "min_level": 0,
- "inventory_tracked": false
}
]
}Catalogue product/service. description, uom and tax are required —
there is no default VAT code (the Konto MCP server fills C62 / Z for
you; the API does not). unit_price defaults to 0. The item number is
assigned automatically. result is the new item's guid.
A refusal is HTTP 200 with status: false and Description is required,
Unit of measure is required, Tax is required or Data item invalidate.
| Idempotency-Key | string [ 1 .. 128 ] characters Example: 7c1f0d2e-ops-4711 Optional on any write. A retry with the same key and the same request
(path and body) replays the stored response — same HTTP status, plus the
header |
required | string or ItemCreate (object) |
{- "data": "string"
}{- "status": true,
- "message": "string",
- "result": "614669f6-3560-11e7-8d19-408d5c6208bc"
}Includes the stock lots.
| guid required | string The resource's GUID. |
{- "status": true,
- "message": "string",
- "result": {
- "guid": "43521ec8-3413-11e7-b148-408d5c6208bc",
- "item_number": "1024",
- "description": "Ráðgjöf",
- "uom": "HUR",
- "tax": "S",
- "unit_price": "15000",
- "category": "",
- "active": 1,
- "updated_timestamp": "2026-10-01",
- "qty": 0,
- "qty_available": 0,
- "min_level": 0,
- "inventory_tracked": false
}
}Send the fields to change — but always send unit_price: an update
without it sets the price to 0. The other fields keep their values when
omitted. result is the item's guid.
| guid required | string The resource's GUID. |
| Idempotency-Key | string [ 1 .. 128 ] characters Example: 7c1f0d2e-ops-4711 Optional on any write. A retry with the same key and the same request
(path and body) replays the stored response — same HTTP status, plus the
header |
required | string or ItemCreate (object) |
{- "data": "string"
}{- "status": true,
- "message": "string",
- "result": "614669f6-3560-11e7-8d19-408d5c6208bc"
}Recurring templates, group invoices and hidden invoices are not listed.
Drafts are (status Draft). Outside sync mode, omitting limit returns
every matching invoice, newest issue date first.
Send updated_since and/or cursor for sync mode: rows in a stable (updated, id) order, limit per page (default 100, max 500), has_more and next_cursor on the envelope. Pass next_cursor back as cursor until has_more is false. sort, page, date_filter, from_date and to_date are then ignored.
| limit | integer >= 1 Page size. Without it every match is returned in one response (there is no default page size). In sync mode default 100, max 500. |
| page | integer Default: 1 Page number (default 1). |
| accounting_status | string Example: accounting_status=Created,Error Comma-separated list of |
| project_guid | string Only invoices linked to this project. An unknown GUID returns |
| date_filter | string Default: "issue_date" Enum: "issue_date" "created_date" Which date |
| from_date | string <date> Start date (YYYY-MM-DD). |
| to_date | string <date> End date (YYYY-MM-DD). |
| sort | string Default: "date_desc" Enum: "date_desc" "date_asc" "created_desc" "created_asc"
|
| updated_since | string Example: updated_since=2026-10-01T00:00:00Z Sync mode: only rows whose |
| cursor | string Sync mode: the |
{- "status": true,
- "message": "string",
- "result": [
- {
- "guid": "string",
- "number": "string",
- "type": "invoice",
- "status": "string",
- "amount": "string",
- "currency": "string",
- "exchange_rate": 0,
- "created_date": "string",
- "issue_date": "string",
- "due_date": "string",
- "settlement_date": "string",
- "paid_date": "string",
- "delivery_date": "string",
- "description": "string",
- "booking": "string",
- "cost_provide": "string",
- "terms": "string",
- "refer_guid": "string",
- "updated_timestamp": "string",
- "accounting_status": "string",
- "accounting_message": "string",
- "claim_id": "string",
- "claim_status": "",
- "collection_cost": 0,
- "other_default_costs_amount": 0,
- "default_charge_amount": 0,
- "default_interest_amount": 0,
- "capital_gains_tax": 0,
- "bank_transaction_amount": "string",
- "xml_status": "string",
- "project_guid": "string",
- "project_number": "string",
- "show_project_link": true,
- "customer": {
- "guid": "string",
- "name": "string",
- "address": "string",
- "zip": "string",
- "city": "string",
- "registration_no": "string",
- "email": "string"
}, - "items": [
- {
- "guid": "string",
- "item_number": "string",
- "description": "string",
- "qty": "string",
- "uom": "string",
- "unit_price": "string",
- "discount": 0,
- "discount_type": 0,
- "tax": "string",
- "vat": 0,
- "vat_amount": "string"
}
], - "total_24vat": "string",
- "total_11vat": "string",
- "total_0vat": "string"
}
], - "limit": 0,
- "has_more": true,
- "next_cursor": "string"
}Creates and issues an invoice — Konto delivers it to the customer per
their delivery setting. amount must equal Σ(line items) + VAT.
For a credit note, send type: credit + ref_invoice_guid (the original
is marked credited and its customer is inherited).
result is the new invoice's guid. With save: 1 the invoice is
stored as a draft instead: nothing is sent, and the answer is the same
201 with the draft's guid.
Sending a catalogue line (guid) with your own description, uom,
unit_price or tax also updates that catalogue item to those values.
A refusal is HTTP 200 with status: false, the reason in message — for
example Amount is required, Currency is required, Customer is required, Settlement date is required, Issue date is smaller than now
(issue date in the future), Settlement date is older than the due date,
Type is required (invoice or credit), Item number is required, The calculated total amount of all item lines not equal to the total amount,
an empty account balance, a used-up claim quota, or error_code
claim_not_configured / customer_mismatch / feature_required.
| Idempotency-Key | string [ 1 .. 128 ] characters Example: 7c1f0d2e-ops-4711 Optional on any write. A retry with the same key and the same request
(path and body) replays the stored response — same HTTP status, plus the
header |
required | string or InvoiceCreate (object) JSON-encoded InvoiceCreate object (stringify before sending). |
{- "data": "{\"amount\":24800,\"currency\":\"ISK\",\"customer\":{\"guid\":\"c1a2…\"},\"issue_date\":\"2026-07-13\",\"due_date\":\"2026-07-27\",\"settlement_date\":\"2026-08-10\",\"type\":\"invoice\",\"items\":[{\"add_new\":1,\"description\":\"Consulting\",\"qty\":10,\"unit_price\":2000,\"uom\":\"HUR\",\"tax\":\"S\",\"item_number\":\"10000001\"}]}"
}{- "status": true,
- "message": "string",
- "result": null
}Any of the account's invoices by guid, drafts, recurring templates and credit notes included.
| guid required | string The resource's GUID. |
{- "status": true,
- "message": "string",
- "result": {
- "guid": "string",
- "number": "string",
- "type": "invoice",
- "status": "string",
- "amount": "string",
- "currency": "string",
- "exchange_rate": 0,
- "created_date": "string",
- "issue_date": "string",
- "due_date": "string",
- "settlement_date": "string",
- "paid_date": "string",
- "delivery_date": "string",
- "description": "string",
- "booking": "string",
- "cost_provide": "string",
- "terms": "string",
- "refer_guid": "string",
- "updated_timestamp": "string",
- "accounting_status": "string",
- "accounting_message": "string",
- "claim_id": "string",
- "claim_status": "",
- "collection_cost": 0,
- "other_default_costs_amount": 0,
- "default_charge_amount": 0,
- "default_interest_amount": 0,
- "capital_gains_tax": 0,
- "bank_transaction_amount": "string",
- "xml_status": "string",
- "project_guid": "string",
- "project_number": "string",
- "show_project_link": true,
- "customer": {
- "guid": "string",
- "name": "string",
- "address": "string",
- "zip": "string",
- "city": "string",
- "registration_no": "string",
- "email": "string"
}, - "items": [
- {
- "guid": "string",
- "item_number": "string",
- "description": "string",
- "qty": "string",
- "uom": "string",
- "unit_price": "string",
- "discount": 0,
- "discount_type": 0,
- "tax": "string",
- "vat": 0,
- "vat_amount": "string"
}
], - "total_24vat": "string",
- "total_11vat": "string",
- "total_0vat": "string"
}
}Updates only the bookkeeping accounting status (and an optional
message). It cannot edit amounts, dates, line items or the customer.
Any of the four statuses can be set, in any order. result is the
invoice's guid; a bad status is refused with Accounting status is required.
| guid required | string The resource's GUID. |
| Idempotency-Key | string [ 1 .. 128 ] characters Example: 7c1f0d2e-ops-4711 Optional on any write. A retry with the same key and the same request
(path and body) replays the stored response — same HTTP status, plus the
header |
required | string or InvoiceAccountingUpdate (object) The accounting update, JSON-encoded (or as an object). |
{- "data": "{\"accounting_status\":\"Posted\",\"accounting_message\":\"Bókað í DK\"}"
}{- "status": true,
- "message": "string",
- "result": "614669f6-3560-11e7-8d19-408d5c6208bc"
}A template that auto-generates invoices on a schedule. Same amount,
line-item and customer rules as a normal invoice, with two differences:
for ISK each line's net amount and VAT are rounded to whole krónur before
they are summed, and due_date must be at least 72 hours from now.
result is the recurring schedule's guid.
| Idempotency-Key | string [ 1 .. 128 ] characters Example: 7c1f0d2e-ops-4711 Optional on any write. A retry with the same key and the same request
(path and body) replays the stored response — same HTTP status, plus the
header |
required | string or RecurringInvoiceCreate (object) JSON-encoded RecurringInvoiceCreate object. |
{- "data": "string"
}{- "status": true,
- "message": "string",
- "result": "614669f6-3560-11e7-8d19-408d5c6208bc"
}The number of invoices matching the filters. Takes the filters of
GET /api/v1/agent/invoices except paging and sorting.
The count covers every invoice record on the account, including recurring-invoice templates and grouped or hidden invoices that the list endpoint leaves out, so it can be higher than the number of invoices the list returns.
Known issue: with date_filter=created_date, to_date currently acts as
a second lower bound rather than an upper bound. Filter on the issue date
(the default) for reliable ranges.
| accounting_status | string Example: accounting_status=Created,Error Comma-separated list of |
| date_filter | string Default: "issue_date" Enum: "issue_date" "created_date" Which date |
| from_date | string <date> Start date (YYYY-MM-DD). |
| to_date | string <date> End date (YYYY-MM-DD). |
| project_guid | string Only invoices linked to this project. An unknown GUID returns |
| updated_since | string Example: updated_since=2026-10-01T00:00:00Z Only invoices modified at or after this time: |
{- "status": true,
- "message": "string",
- "result": 42
}Invoice counts and totals for a period, grouped by status and currency — the figures behind Konto's dashboard cards. Read from pre-computed monthly buckets, so the cost does not grow with invoice volume.
Pick one period mode (evaluated in this order):
| Mode | Parameters | Example |
|---|---|---|
| Custom range | from_date + to_date |
?from_date=2026-01-01&to_date=2026-04-30 |
| Single month | year + month |
?year=2026&month=4 |
| Months within one year (e.g. a VAT period) | year + from_month + to_month |
?year=2026&from_month=1&to_month=2 |
| Full year | year |
?year=2026 |
Buckets are monthly, so a custom range is widened to whole months:
from_date=2026-01-15&to_date=2026-04-15 covers 2026-01-01 – 2026-04-30
(see period in the response). Invoices are placed by issue date.
Statuses:
paid — paid invoices. Credit notes are not counted here.sent — issued and unpaid, not past the settlement date (eindagi), no active collection case.overdue — issued and unpaid, past the settlement date, no active collection case.collection — issued and unpaid, with an active collection case.total — always the first entry: the sum of the four above.Apart from total, only statuses with data are listed. Amounts include
VAT, stay in the invoice currency (never converted), and are rounded to 0
decimals for ISK and 2 for other currencies. Credit notes count negative
in sent, overdue and collection.
The response is not wrapped in result: period and summaries
sit at the top level next to status.
Requires the dashboard_data feature on the account's plan; without it
the reply is status: false with a "Subscription does not include the
required feature" message.
| year | integer Example: year=2026 Calendar year. Alone for a full year, with |
| month | integer [ 1 .. 12 ] Example: month=4 1–12, with |
| from_month | integer [ 1 .. 12 ] Example: from_month=1 1–12, with |
| to_month | integer [ 1 .. 12 ] Example: to_month=2 1–12, with |
| from_date | string <date> Start date (YYYY-MM-DD). |
| to_date | string <date> End date (YYYY-MM-DD). |
{- "status": true,
- "period": {
- "from": "2026-01-01",
- "to": "2026-03-31"
}, - "summaries": [
- {
- "status": "total",
- "count": 42,
- "amounts": [
- {
- "currency": "ISK",
- "total": 500000
}, - {
- "currency": "EUR",
- "total": 1250.5
}
]
}, - {
- "status": "paid",
- "count": 30,
- "amounts": [
- {
- "currency": "ISK",
- "total": 400000
}, - {
- "currency": "EUR",
- "total": 1250.5
}
]
}, - {
- "status": "sent",
- "count": 5,
- "amounts": [
- {
- "currency": "ISK",
- "total": 50000
}
]
}, - {
- "status": "overdue",
- "count": 4,
- "amounts": [
- {
- "currency": "ISK",
- "total": 30000
}
]
}, - {
- "status": "collection",
- "count": 3,
- "amounts": [
- {
- "currency": "ISK",
- "total": 20000
}
]
}
]
}Pages by default: 10 records per page unless you send limit
(limit=0 returns everything). A paged reply also carries hasMore,
limit, page and next_url (a legacy-API URL; build the next request
yourself with page + 1). Newest issue date first unless you pass
sort. Each record includes its file and xml base64, so keep pages
small. Deleted records and records Cost AI is still reading are not
listed.
Send updated_since and/or cursor for sync mode: rows in a stable (updated, id) order, limit per page (default 100, max 500), has_more and next_cursor on the envelope. Pass next_cursor back as cursor until has_more is false. sort and page are then ignored; the other filters still apply.
| limit | integer >= 0 Default: 10 Page size. Default 10; |
| page | integer Default: 1 Page number (default 1). |
| accounting_status | string Example: accounting_status=New,Created Comma-separated list of |
| project_guid | string Only cost records linked to this project. An unknown GUID returns |
| updated_since | string Example: updated_since=2026-10-01T00:00:00Z Sync mode: only rows whose |
| cursor | string Sync mode: the |
| type | string Example: type=2353 Exact cost code (see |
| supplier_id | string Exact supplier kennitala / id. |
| date_filter | string Default: "date" Enum: "date" "created_date" Which date |
| from_date | string <date> Start date (YYYY-MM-DD). |
| to_date | string <date> End date (YYYY-MM-DD). |
| sort | string Default: "date_desc" Enum: "date_desc" "date_asc" "created_desc" "created_asc"
|
{- "status": true,
- "message": "string",
- "result": [
- {
- "guid": "string",
- "description": "string",
- "supplier_id": "string",
- "amount": "string",
- "currency": "string",
- "vat_AA": "string",
- "vat_S": "string",
- "cost_code": "string",
- "how_paid": null,
- "issue_date": "string",
- "created_date": "string",
- "updated_timestamp": "string",
- "accounting_status": "New",
- "file": "string",
- "file_name": "string",
- "file_extension": "string",
- "xml": "string",
- "project_name": "string",
- "project_guid": "string",
- "project_number": "string",
- "project_subtotal": "string",
- "project_invoiced_amount": "string",
- "project_invoice_guid": "string"
}
], - "hasMore": true,
- "page": 0,
- "limit": 0,
- "next_url": "string",
- "has_more": true,
- "next_cursor": "string"
}Upload a receipt/invoice image or PDF (multipart/form-data, max 5 MB; images are scaled down to 1028 px).
queue: true; the record stays
out of GET /costs until the AI is done, so poll
GET /costs/{guid}. date is optional and description is not
stored. Each upload counts against a monthly AI allowance (2 × the
account's available credits); past it the answer is status: false
with code: cost_limit_reached (HTTP 200).date is required and the record is created at once
with accounting status Created, holding just the file, date and
description.If you already have the numbers, use /costs/advanced instead.
result is the new record's guid. Refusals are HTTP 200 with
status: false: Field date is required and must be format Y-m-d,
Field file is required, File must be jpg, jpeg, png, gif or pdf,
File size must not exceed 5MB.
| Idempotency-Key | string [ 1 .. 128 ] characters Example: 7c1f0d2e-ops-4711 Optional on any write. A retry with the same key and the same request
(path and body) replays the stored response — same HTTP status, plus the
header |
| date | string <date>
|
| description | string Stored only when Cost AI is off. |
| project_guid | string Put the record on this project (needs the Projects add-on). |
| file required | string <binary> jpg, jpeg, png, gif or pdf; ≤ 5 MB. |
{- "status": true,
- "message": "string",
- "result": null,
- "code": "string"
}Record a cost from numbers you already have. Fields are sent flat at
the top level (no data wrapper), as JSON — or as multipart/form-data
to attach the receipt. For a credit note set credit_note: 1 and keep
amount positive. The record may be approved at once if the account's
auto-approve rules match. result is the new record's guid.
Refusals are HTTP 200 with status: false: Field date is required and must be format Y-m-d, Field amount is required and must be a positive number, Field how_paid is required, Field supplier_name is required, Field supplier_id is required, Field type is required (an
unknown cost code), or a file error.
| Idempotency-Key | string [ 1 .. 128 ] characters Example: 7c1f0d2e-ops-4711 Optional on any write. A retry with the same key and the same request
(path and body) replays the stored response — same HTTP status, plus the
header |
| date required | string <date>
|
| amount required | number > 0 Total including VAT. Positive, also for a credit note. |
| how_paid required | integer Enum: 1 2 3 4 1=Account, 2=Debit card, 3=Credit card, 4=Owner cash. |
| supplier_name required | string |
| supplier_id required | string Supplier kennitala / ID. |
| type required | string Enum: "3028" "2173" "3033" "3085" "3090" "2093" "2243" "2193" "2423" "2443" "2353" "2383" "2403" "2263" "3163" "2333" "3140" "2283" "2533" "2633" "3653" "5028" "2153" "3080" "9535" Cost code (numeric string). Accepted: |
| description | string |
| vat_11 | number VAT amount in the 11% bracket — an amount, not a rate. |
| vat_24 | number VAT amount in the 24% bracket. |
| credit_note | integer Enum: 0 1 1 to record as a credit note; keep amount positive. |
| project_guid | string Put the record on this project (needs the Projects add-on). |
{- "date": "2019-08-24",
- "amount": 1,
- "how_paid": 1,
- "supplier_name": "string",
- "supplier_id": "string",
- "type": "3028",
- "description": "string",
- "vat_11": 0,
- "vat_24": 0,
- "credit_note": 0,
- "project_guid": "string"
}{- "status": true,
- "message": "string",
- "result": null
}Takes the list's filters except paging and sorting. Unlike the list it
also counts records Cost AI is still reading, so it can be higher than
the number of records GET /costs returns.
| accounting_status | string Comma-separated, as on the list. |
| type | string |
| supplier_id | string |
| project_guid | string |
| date_filter | string Default: "date" Enum: "date" "created_date" |
| from_date | string <date> Start date (YYYY-MM-DD). |
| to_date | string <date> End date (YYYY-MM-DD). |
| updated_since | string Only records modified at or after this time (see the list). |
{- "status": true,
- "message": "string",
- "result": 42
}| guid required | string The resource's GUID. |
{- "status": true,
- "message": "string",
- "result": {
- "guid": "string",
- "description": "string",
- "supplier_id": "string",
- "amount": "string",
- "currency": "string",
- "vat_AA": "string",
- "vat_S": "string",
- "cost_code": "string",
- "how_paid": null,
- "issue_date": "string",
- "created_date": "string",
- "updated_timestamp": "string",
- "accounting_status": "New",
- "file": "string",
- "file_name": "string",
- "file_extension": "string",
- "xml": "string",
- "project_name": "string",
- "project_guid": "string",
- "project_number": "string",
- "project_subtotal": "string",
- "project_invoiced_amount": "string",
- "project_invoice_guid": "string"
}
}For bookkeeping software: records what happened to an approved record.
Only a record whose status is Created can be updated, and only to
Posted, Skipped or Error — Created itself is set by Konto, and
Posted is terminal. To edit a Created record's data, move it to New
first, then re-approve. result is the record's guid.
Refusals (HTTP 200, status: false): Accounting status must be one of: Posted, Skipped, Error, Only costs with accounting_status Created can be updated via the API, No cost found, Data cost invalidate.
| guid required | string The resource's GUID. |
| Idempotency-Key | string [ 1 .. 128 ] characters Example: 7c1f0d2e-ops-4711 Optional on any write. A retry with the same key and the same request
(path and body) replays the stored response — same HTTP status, plus the
header |
required | string or object JSON-encoded |
{- "data": "{\"accounting_status\":\"Posted\"}"
}{- "status": true,
- "message": "string",
- "result": "614669f6-3560-11e7-8d19-408d5c6208bc"
}Moves the record to Konto's recycle bin: it disappears from the API at
once, the user can restore it in Konto for 28 days, and then it is purged.
Prefer status Skipped to exclude a record from bookkeeping. Refused
(HTTP 200, status: false) for a Posted record (retryable: false)
and while the record is being processed (retryable: true,
retry_after seconds).
| guid required | string The resource's GUID. |
| Idempotency-Key | string [ 1 .. 128 ] characters Example: 7c1f0d2e-ops-4711 Optional on any write. A retry with the same key and the same request
(path and body) replays the stored response — same HTTP status, plus the
header |
{- "status": true,
- "message": "string",
- "result": null,
- "retryable": true,
- "retry_after": 0
}Moves an approved (Created), non-Posted cost back to New so it can be
edited in Konto; re-approving regenerates its bookkeeping XML. result
is the record's guid. Otherwise status: false with No cost found or
This cost cannot be moved to New (only approved, non-Posted costs can be re-opened for editing).
| guid required | string The resource's GUID. |
| Idempotency-Key | string [ 1 .. 128 ] characters Example: 7c1f0d2e-ops-4711 Optional on any write. A retry with the same key and the same request
(path and body) replays the stored response — same HTTP status, plus the
header |
{- "status": true,
- "message": "string",
- "result": "614669f6-3560-11e7-8d19-408d5c6208bc"
}Projects group tasks, cost records, sales invoices and scope lines for one
customer and track what has been billed and what is still outstanding.
Scopes: project_read (reads) or project (reads and writes). The account
needs the Projects add-on — without it the consent screen drops both
scopes, and a call answers HTTP 200 status: false naming the missing feature.
project_cost_id, product_id) from the project's
costs / products (?expand=costs,products).data field: a JSON object, or
the same object JSON-encoded as a string. Every other write takes top-level
fields. PUT and DELETE bodies must be application/json. Do not repeat a
path parameter in the body: a body key with the same name (guid,
cost_guid, …) replaces the path value.status: false.
Conflicts are 409 and malformed version / Idempotency-Key /
updated_since / cursor values 400, both with an error_code.
Creates answer 201. A token without the scope gets a real 403.external_ref — your own id (max 128 characters), unique per account.
Filter with ?external_ref=; a create with an existing one returns that
project (existing: true) instead of a duplicate.version — +1 on every change to the project's own fields, made in
Konto or through the API. Send it with PUT / DELETE to get 409
version_conflict (with current_version) instead of overwriting a newer
edit. Linking or unlinking costs, invoices, scope lines or related projects
does not change the project's version or updated_at.Idempotency-Key — optional header on every write (see the parameter).updated_since / cursor on the list switch to keyset paging
over updated_at; include_removed=1 adds removed projects.project_guid
on their own create endpoints, and filtered with ?project_guid=.action_id in the envelope.Templates are never listed; removed projects only with include_removed=1.
from_date / to_date filter on the creation date.
Paging. Without limit, every matching project is returned in one
response (there is no default page size). With limit the envelope also
carries total, page and limit.
Sync mode. updated_since and/or cursor switch to keyset paging:
rows ordered by (updated_at, id) ascending, limit default 100 / max
500, has_more and next_cursor on the envelope — pass next_cursor
back as cursor. sort, sort_type and page are then ignored; every
other filter (including from_date / to_date) still applies.
totals is included only with with_totals=1 (computed per project).
| status | string Example: status=active
|
| search_text | string Substring match on name, project number (digits only), owner team, category or customer name. |
| customer_guid | string Only this customer's projects. An unknown or deactivated customer is refused ("No customer found"). |
| external_ref | string <= 128 characters Exact match on your own reference. |
| from_date | string <date> Start date (YYYY-MM-DD). |
| to_date | string <date> End date (YYYY-MM-DD). |
| sort | string Default: "created_at" Enum: "created_at" "name" "start_date" "updated_at" Sort column (paged / unpaged mode only). Any other value falls back to |
| sort_type | string Default: "down" Enum: "down" "up"
|
| limit | integer >= 1 Page size. Without it every match is returned in one response. In sync mode default 100, max 500. |
| page | integer Default: 1 Page number (default 1). |
| with_totals | boolean Default: false
|
| expand | string Example: expand=costs,products,invoices Comma-separated linked collections to include: |
| include_removed | string Default: "0" Enum: "0" "1"
|
| updated_since | string Example: updated_since=2026-10-01T00:00:00Z Sync mode: only rows whose |
| cursor | string Sync mode: the |
{- "status": true,
- "message": "string",
- "result": [
- {
- "guid": "8f3a6c2e-8d40-11ef-9c3a-0242ac120002",
- "project_number": "PRJ-12",
- "external_ref": "OPS-4711",
- "name": "Nýbygging Lækjargata 4",
- "status": 1,
- "status_label": "active",
- "customer": {
- "guid": "5d1e2c4a-8b7f-11ef-9c3a-0242ac120002",
- "name": "Byggir ehf.",
- "registration_no": "4602070880",
- "email": "bokhald@byggir.is"
}, - "owner_team": "Teymi A",
- "category": "Nýbygging",
- "start_date": "2026-10-01",
- "end_date": "",
- "estimate_amount": "1500000",
- "sort_note": "Innréttingar og gifsveggir á 2. hæð",
- "full_note": "",
- "is_template": false,
- "invoice_created": false,
- "page_published": false,
- "public_url": "",
- "version": 3,
- "created_at": "2026-10-01 09:30:15",
- "updated_at": "2026-10-12 14:02:41"
}
], - "total": 0,
- "page": 0,
- "limit": 0,
- "has_more": true,
- "next_cursor": "string"
}A new project is always active and gets the account's next PRJ-n
number unless project_number is given. Scope lines are created with it:
a product line becomes a scope line, a service line becomes a task on
the project. Prefill from a saved template (template_guid) or a quote
(quote_guid); fields you send win.
If external_ref matches an existing project, nothing is created: the
response is HTTP 200 with existing: true, result = that project's
guid and project = that project (without totals). Otherwise 201,
result = the new guid and project = the new project with its
products and tasks.
| Idempotency-Key | string [ 1 .. 128 ] characters Example: 7c1f0d2e-ops-4711 Optional on any write. A retry with the same key and the same request
(path and body) replays the stored response — same HTTP status, plus the
header |
The project as data — a JSON object, or the same object JSON-encoded as a string.
required | ProjectCreate (object) or string |
{- "data": {
- "name": "Nýbygging Lækjargata 4",
- "customer_guid": "5d1e2c4a-8b7f-11ef-9c3a-0242ac120002",
- "external_ref": "OPS-4711",
- "start_date": "2026-10-01",
- "end_date": "2026-12-15",
- "estimate_amount": 1500000,
- "scope": [
- {
- "type": "product",
- "description": "Gifsplötur 12,5 mm",
- "qty": 40,
- "unit_price": 2490,
- "tax": "S"
}, - {
- "type": "service",
- "description": "Uppsetning",
- "estimated": 450000
}
]
}
}{- "status": true,
- "message": "string",
- "result": "string",
- "project": {
- "guid": "8f3a6c2e-8d40-11ef-9c3a-0242ac120002",
- "project_number": "PRJ-12",
- "external_ref": "OPS-4711",
- "name": "Nýbygging Lækjargata 4",
- "status": 1,
- "status_label": "active",
- "customer": {
- "guid": "5d1e2c4a-8b7f-11ef-9c3a-0242ac120002",
- "name": "Byggir ehf.",
- "registration_no": "4602070880",
- "email": "bokhald@byggir.is"
}, - "owner_team": "Teymi A",
- "category": "Nýbygging",
- "start_date": "2026-10-01",
- "end_date": "",
- "estimate_amount": "1500000",
- "sort_note": "Innréttingar og gifsveggir á 2. hæð",
- "full_note": "",
- "is_template": false,
- "invoice_created": false,
- "page_published": false,
- "public_url": "",
- "version": 3,
- "created_at": "2026-10-01 09:30:15",
- "updated_at": "2026-10-12 14:02:41"
}, - "existing": true
}Same filters as the list (status, search_text, customer_guid, external_ref, from_date, to_date, include_removed, updated_since). result is a bare integer.
| status | string
|
| search_text | string |
| customer_guid | string |
| external_ref | string <= 128 characters |
| from_date | string <date> Start date (YYYY-MM-DD). |
| to_date | string <date> End date (YYYY-MM-DD). |
| include_removed | string Default: "0" Enum: "0" "1"
|
| updated_since | string Example: updated_since=2026-10-01T00:00:00Z Sync mode: only rows whose |
{- "status": true,
- "message": "string",
- "result": 14
}The account's saved "New Project" templates with their scope lines, in the shape create accepts — pass a template's guid as template_guid, or its scope as scope. Template guids are not projects; the other project endpoints answer "No project found" for them.
{- "status": true,
- "message": "string",
- "result": [
- {
- "guid": "string",
- "name": "string",
- "sort_note": "string",
- "full_note": "string",
- "category": "string",
- "owner_team": "string",
- "scope": [
- {
- "type": "product",
- "description": "string",
- "item_guid": "string",
- "qty": 1,
- "unit_price": 0,
- "tax": "S",
- "discount_type": "percent",
- "discount_value": 0,
- "estimated": 0
}
], - "created_at": "string"
}
]
}Always includes totals. Add expand= for linked rows. Also returns a removed project (status 5), though every write to it is refused.
| guid required | string <uuid> The project's GUID. |
| expand | string Example: expand=costs,products,invoices Comma-separated linked collections to include: |
{- "status": true,
- "message": "string",
- "result": {
- "guid": "8f3a6c2e-8d40-11ef-9c3a-0242ac120002",
- "project_number": "PRJ-12",
- "external_ref": "OPS-4711",
- "name": "Nýbygging Lækjargata 4",
- "status": 1,
- "status_label": "active",
- "customer": {
- "guid": "5d1e2c4a-8b7f-11ef-9c3a-0242ac120002",
- "name": "Byggir ehf.",
- "registration_no": "4602070880",
- "email": "bokhald@byggir.is"
}, - "owner_team": "Teymi A",
- "category": "Nýbygging",
- "start_date": "2026-10-01",
- "end_date": "",
- "estimate_amount": "1500000",
- "sort_note": "Innréttingar og gifsveggir á 2. hæð",
- "full_note": "",
- "is_template": false,
- "invoice_created": false,
- "page_published": false,
- "public_url": "",
- "version": 3,
- "created_at": "2026-10-01 09:30:15",
- "updated_at": "2026-10-12 14:02:41"
}
}Only the keys present in data change. status cannot be set to
removed — use DELETE. A removed project cannot be updated (or restored)
through the API. Send version (in data or top level) for an
optimistic check. A timeline entry is written only when the status
actually changes. result is the updated project (without totals).
| guid required | string <uuid> The project's GUID. |
| Idempotency-Key | string [ 1 .. 128 ] characters Example: 7c1f0d2e-ops-4711 Optional on any write. A retry with the same key and the same request
(path and body) replays the stored response — same HTTP status, plus the
header |
The fields to change as data (object or JSON-encoded string). version may also be sent at the top level.
required | ProjectUpdate (object) or string |
| version | integer >= 1 Alternative to |
{- "data": {
- "status": "on_hold",
- "version": 3
}
}{- "status": true,
- "message": "string",
- "result": {
- "guid": "8f3a6c2e-8d40-11ef-9c3a-0242ac120002",
- "project_number": "PRJ-12",
- "external_ref": "OPS-4711",
- "name": "Nýbygging Lækjargata 4",
- "status": 1,
- "status_label": "active",
- "customer": {
- "guid": "5d1e2c4a-8b7f-11ef-9c3a-0242ac120002",
- "name": "Byggir ehf.",
- "registration_no": "4602070880",
- "email": "bokhald@byggir.is"
}, - "owner_team": "Teymi A",
- "category": "Nýbygging",
- "start_date": "2026-10-01",
- "end_date": "",
- "estimate_amount": "1500000",
- "sort_note": "Innréttingar og gifsveggir á 2. hæð",
- "full_note": "",
- "is_template": false,
- "invoice_created": false,
- "page_published": false,
- "public_url": "",
- "version": 3,
- "created_at": "2026-10-01 09:30:15",
- "updated_at": "2026-10-12 14:02:41"
}
}Sets status 5 (removed), like the Delete button in Konto. Tasks, cost records and invoices keep their link; the project leaves every list (still visible with include_removed=1 or by guid). There is no restore through the API. version may be sent as a query parameter or in a JSON body. result is the project's guid.
| guid required | string <uuid> The project's GUID. |
| version | integer >= 1 Optimistic check: the project's current |
| Idempotency-Key | string [ 1 .. 128 ] characters Example: 7c1f0d2e-ops-4711 Optional on any write. A retry with the same key and the same request
(path and body) replays the stored response — same HTTP status, plus the
header |
{- "status": true,
- "message": "string",
- "result": "string"
}Newest first. Works for removed projects too.
| guid required | string <uuid> The project's GUID. |
| limit | integer [ 1 .. 500 ] Default: 50 Number of entries (default 50, max 500). |
{- "status": true,
- "message": "string",
- "result": [
- {
- "log_id": 2214,
- "type": "cost_added",
- "params": {
- "supplier": "Húsasmiðjan hf.",
- "amount": 24800,
- "currency": "ISK"
}, - "message": "Cost record added — Húsasmiðjan hf. (24.800 ISK)",
- "created_at": "2026-10-09 10:14:03"
}
]
}Links one (cost_guid) or several (cost_guids) of the account's cost
records. All-or-nothing: every record is checked before any is linked —
each must exist, not be deleted, and not be on a project yet (a cost
record belongs to at most one project; 409 already_linked
otherwise). The billable subtotal defaults to the record's own amount.
Writes the project timeline and the record's history. Returns HTTP 200
with one cost row per linked record.
| guid required | string <uuid> The project's GUID. |
| Idempotency-Key | string [ 1 .. 128 ] characters Example: 7c1f0d2e-ops-4711 Optional on any write. A retry with the same key and the same request
(path and body) replays the stored response — same HTTP status, plus the
header |
| cost_guid | string One cost record. |
Array of strings or string Several cost records — an array or a comma-separated string. Linked all-or-nothing. | |
| subtotal | number >= 0 Billable amount, in the record's currency. Single record only (refused with |
{- "cost_guid": "b7e0c1d2-8d11-11ef-9c3a-0242ac120002",
- "subtotal": 21500
}{- "status": true,
- "message": "string",
- "result": [
- {
- "project_cost_id": 318,
- "is_manual": false,
- "cost_guid": "b7e0c1d2-8d11-11ef-9c3a-0242ac120002",
- "supplier": "Húsasmiðjan hf.",
- "description": "Gifsplötur og skrúfur",
- "date": "2026-10-08",
- "currency": "ISK",
- "full": "24800",
- "subtotal": "21500",
- "discount": "3300",
- "invoice_amount": "0",
- "invoiced": false,
- "invoice_guid": "",
- "project_file_id": 0,
- "created_at": "2026-10-09 10:14:03"
}
]
}Sets subtotal — the amount billable to the customer for this row,
independent of the cost record's own amount (the record is not
changed). Refused once the row has been invoiced (409
already_invoiced). To set the subtotal of a manual cost line
instead, send its project_cost_id in the body; it takes precedence
over the path's cost_guid.
| guid required | string <uuid> The project's GUID. |
| cost_guid required | string GUID of a cost record linked to this project. |
| Idempotency-Key | string [ 1 .. 128 ] characters Example: 7c1f0d2e-ops-4711 Optional on any write. A retry with the same key and the same request
(path and body) replays the stored response — same HTTP status, plus the
header |
| subtotal required | number >= 0 Amount billable to the customer, in the row's currency. A decimal comma is accepted in strings. |
| project_cost_id | integer Address a manual cost line instead of the path's cost record (takes precedence). |
{- "subtotal": 18000
}{- "status": true,
- "message": "string",
- "result": {
- "project_cost_id": 318,
- "is_manual": false,
- "cost_guid": "b7e0c1d2-8d11-11ef-9c3a-0242ac120002",
- "supplier": "Húsasmiðjan hf.",
- "description": "Gifsplötur og skrúfur",
- "date": "2026-10-08",
- "currency": "ISK",
- "full": "24800",
- "subtotal": "21500",
- "discount": "3300",
- "invoice_amount": "0",
- "invoiced": false,
- "invoice_guid": "",
- "project_file_id": 0,
- "created_at": "2026-10-09 10:14:03"
}
}Clears the record's project link and deletes the billing row (a custom subtotal is lost); the cost record itself is otherwise untouched. Refused once the row has been invoiced (409 already_invoiced). For a manual cost line use DELETE …/manual-costs/{id}. result is the cost record's guid.
| guid required | string <uuid> The project's GUID. |
| cost_guid required | string GUID of a cost record linked to this project. |
| Idempotency-Key | string [ 1 .. 128 ] characters Example: 7c1f0d2e-ops-4711 Optional on any write. A retry with the same key and the same request
(path and body) replays the stored response — same HTTP status, plus the
header |
{- "status": true,
- "message": "string",
- "result": "string"
}A cost that belongs only to the project (wages, a subcontractor on a contract) and never becomes a cost record. ISK only. Its subtotal starts equal to amount. Validation errors name the input in field.
| guid required | string <uuid> The project's GUID. |
| Idempotency-Key | string [ 1 .. 128 ] characters Example: 7c1f0d2e-ops-4711 Optional on any write. A retry with the same key and the same request
(path and body) replays the stored response — same HTTP status, plus the
header |
| supplier_name required | string <= 255 characters |
| amount required | number > 0 ISK. Strings may use Icelandic formatting ("84.940", "1.234,50", "84 940 kr."): a comma is the decimal mark and a dot followed by exactly three digits is a thousands separator, so send plain numbers. A minus sign is dropped. |
| cost_date | string
|
| description | string <= 500 characters |
| project_file_id | integer One of the project's files ( |
{- "supplier_name": "Jón Jónsson — laun október",
- "amount": 412000,
- "cost_date": "2026-10-31",
- "description": "Vinnulaun, 80 klst."
}{- "status": true,
- "message": "string",
- "result": null
}Full replacement — send every field again. supplier_name and
amount are required; an omitted cost_date becomes today, and an
omitted description or project_file_id is cleared. A subtotal that
was never customised follows the new amount. Refused once invoiced (409
already_invoiced). A linked cost record's row answers "No cost found".
| guid required | string <uuid> The project's GUID. |
| id required | integer >= 1
|
| Idempotency-Key | string [ 1 .. 128 ] characters Example: 7c1f0d2e-ops-4711 Optional on any write. A retry with the same key and the same request
(path and body) replays the stored response — same HTTP status, plus the
header |
| supplier_name required | string <= 255 characters |
| amount required | number > 0 ISK. Strings may use Icelandic formatting ("84.940", "1.234,50", "84 940 kr."): a comma is the decimal mark and a dot followed by exactly three digits is a thousands separator, so send plain numbers. A minus sign is dropped. |
| cost_date | string
|
| description | string <= 500 characters |
| project_file_id | integer One of the project's files ( |
{- "supplier_name": "Jón Jónsson — laun október",
- "amount": 412000,
- "cost_date": "2026-10-31",
- "description": "Vinnulaun, 80 klst."
}{- "status": true,
- "message": "string",
- "result": {
- "project_cost_id": 318,
- "is_manual": false,
- "cost_guid": "b7e0c1d2-8d11-11ef-9c3a-0242ac120002",
- "supplier": "Húsasmiðjan hf.",
- "description": "Gifsplötur og skrúfur",
- "date": "2026-10-08",
- "currency": "ISK",
- "full": "24800",
- "subtotal": "21500",
- "discount": "3300",
- "invoice_amount": "0",
- "invoiced": false,
- "invoice_guid": "",
- "project_file_id": 0,
- "created_at": "2026-10-09 10:14:03"
}
}Permanently deletes the line (it is the cost; there is no record behind it). Refused once invoiced (409 already_invoiced). result is the deleted project_cost_id.
| guid required | string <uuid> The project's GUID. |
| id required | integer >= 1
|
| Idempotency-Key | string [ 1 .. 128 ] characters Example: 7c1f0d2e-ops-4711 Optional on any write. A retry with the same key and the same request
(path and body) replays the stored response — same HTTP status, plus the
header |
{- "status": true,
- "message": "string",
- "result": 0
}Links one of the account's sent sales invoices. Drafts, quotes,
notes, orders, voided invoices, recurring templates and group invoices
are refused (status false, error_code not_linkable). An invoice can
be on one project only (409 already_linked). The invoice's
accounting status and XML are not touched. result is the invoice object
(same shape as GET /invoices/{guid}).
| guid required | string <uuid> The project's GUID. |
| Idempotency-Key | string [ 1 .. 128 ] characters Example: 7c1f0d2e-ops-4711 Optional on any write. A retry with the same key and the same request
(path and body) replays the stored response — same HTTP status, plus the
header |
| invoice_guid required | string A sent sales invoice of this account. |
{- "invoice_guid": "e93b2a10-8d20-11ef-9c3a-0242ac120002"
}{- "status": true,
- "message": "string",
- "result": {
- "guid": "string",
- "number": "string",
- "type": "invoice",
- "status": "string",
- "amount": "string",
- "currency": "string",
- "exchange_rate": 0,
- "created_date": "string",
- "issue_date": "string",
- "due_date": "string",
- "settlement_date": "string",
- "paid_date": "string",
- "delivery_date": "string",
- "description": "string",
- "booking": "string",
- "cost_provide": "string",
- "terms": "string",
- "refer_guid": "string",
- "updated_timestamp": "string",
- "accounting_status": "string",
- "accounting_message": "string",
- "claim_id": "string",
- "claim_status": "",
- "collection_cost": 0,
- "other_default_costs_amount": 0,
- "default_charge_amount": 0,
- "default_interest_amount": 0,
- "capital_gains_tax": 0,
- "bank_transaction_amount": "string",
- "xml_status": "string",
- "project_guid": "string",
- "project_number": "string",
- "show_project_link": true,
- "customer": {
- "guid": "string",
- "name": "string",
- "address": "string",
- "zip": "string",
- "city": "string",
- "registration_no": "string",
- "email": "string"
}, - "items": [
- {
- "guid": "string",
- "item_number": "string",
- "description": "string",
- "qty": "string",
- "uom": "string",
- "unit_price": "string",
- "discount": 0,
- "discount_type": 0,
- "tax": "string",
- "vat": 0,
- "vat_amount": "string"
}
], - "total_24vat": "string",
- "total_11vat": "string",
- "total_0vat": "string"
}
}Clears the link on both sides. An invoice that was created from this project (it bills the project's tasks, costs or scope lines) cannot be unlinked (409 created_from_project). result is the invoice's guid.
| guid required | string <uuid> The project's GUID. |
| invoice_guid required | string GUID of a sales invoice linked to this project. |
| Idempotency-Key | string [ 1 .. 128 ] characters Example: 7c1f0d2e-ops-4711 Optional on any write. A retry with the same key and the same request
(path and body) replays the stored response — same HTTP status, plus the
header |
{- "status": true,
- "message": "string",
- "result": "string"
}Adds a line item to the project's scope, ad hoc or from the catalogue.
With item_guid only the catalogue description is copied (a sent
description is ignored) — qty, unit_price and tax still come from
the request and default to 1, 0 and 0. estimated defaults to 0 here
(unlike scope lines sent with create). Validation errors name the input
in field.
| guid required | string <uuid> The project's GUID. |
| Idempotency-Key | string [ 1 .. 128 ] characters Example: 7c1f0d2e-ops-4711 Optional on any write. A retry with the same key and the same request
(path and body) replays the stored response — same HTTP status, plus the
header |
| item_guid | string Catalogue item; only its description is copied (a sent |
| description required | string <= 500 characters |
| qty | number > 0 Default: 1 |
| unit_price | number >= 0 Default: 0 ISK, excluding VAT. |
string or number VAT: | |
| discount_type | string Default: "percent" Enum: "percent" "amount" |
| discount_value | number >= 0 Default: 0 A percentage (max 100) or an ISK amount. |
| estimated | number >= 0 Default: 0 |
{- "description": "Parket, eik 14 mm",
- "qty": 65,
- "unit_price": 6890,
- "tax": "S",
- "discount_type": "percent",
- "discount_value": 10
}{- "status": true,
- "message": "string",
- "result": null
}Only the fields sent change; the catalogue link (item_guid) cannot be changed. Refused once invoiced (409 already_invoiced).
| guid required | string <uuid> The project's GUID. |
| id required | integer >= 1
|
| Idempotency-Key | string [ 1 .. 128 ] characters Example: 7c1f0d2e-ops-4711 Optional on any write. A retry with the same key and the same request
(path and body) replays the stored response — same HTTP status, plus the
header |
| description | string <= 500 characters |
| qty | number > 0 |
| unit_price | number >= 0 |
string or number | |
| discount_type | string Enum: "percent" "amount" Any other value is stored as |
| discount_value | number >= 0 |
| estimated | number >= 0 |
{- "qty": 72,
- "unit_price": 6490
}{- "status": true,
- "message": "string",
- "result": {
- "product_id": 0,
- "item_guid": "string",
- "description": "string",
- "qty": "string",
- "unit_price": "string",
- "tax": 0,
- "tax_code": "string",
- "discount_type": "percent",
- "discount_value": 0,
- "subtotal": "string",
- "estimated": "string",
- "invoice_amount": "string",
- "invoiced": true,
- "invoice_guid": "string",
- "created_at": "string"
}
}Permanently deletes the line. Refused once invoiced (409 already_invoiced). result is the deleted product_id.
| guid required | string <uuid> The project's GUID. |
| id required | integer >= 1
|
| Idempotency-Key | string [ 1 .. 128 ] characters Example: 7c1f0d2e-ops-4711 Optional on any write. A retry with the same key and the same request
(path and body) replays the stored response — same HTTP status, plus the
header |
{- "status": true,
- "message": "string",
- "result": 0
}Marks two of the account's live projects as related. Idempotent — an existing link (in either direction) is returned as is. A project cannot be linked to itself. Projects of the same customer are already related automatically (link_type customer under expand=related).
| guid required | string <uuid> The project's GUID. |
| Idempotency-Key | string [ 1 .. 128 ] characters Example: 7c1f0d2e-ops-4711 Optional on any write. A retry with the same key and the same request
(path and body) replays the stored response — same HTTP status, plus the
header |
| related_guid required | string GUID of another live project of this account. |
{- "related_guid": "f0c8d3b4-8d31-11ef-9c3a-0242ac120002"
}{- "status": true,
- "message": "string",
- "result": {
- "link_id": 0,
- "guid": "string",
- "project_number": "string",
- "name": "string"
}
}Newest task first. Archived tasks are left out unless include_removed=1.
Outside sync mode, omitting limit returns every matching task.
type picks a bucket: open = not invoiced yet, invoice = invoiced in
the last 28 days, older = invoiced before that, all = no bucket. An
unknown value falls back to the default.
Send updated_since and/or cursor for sync mode: rows in a stable (updated, id) order, limit per page (default 100, max 500), has_more and next_cursor on the envelope. Pass next_cursor back as cursor until has_more is false. In sync mode type defaults to all.
| type | string Default: "open" Enum: "open" "invoice" "older" "all" Default |
| project_guid | string Only tasks in this project. An unknown GUID returns |
| customer_guid | string Only tasks for this (active) customer. An unknown GUID returns |
| external_ref | string <= 128 characters Only the task with this external reference (max 128 characters). |
| include_removed | string Default: "0" Enum: "0" "1"
|
| limit | integer >= 1 Page size. Without it every match is returned in one response (there is no default page size). In sync mode default 100, max 500. |
| page | integer Default: 1 Page number (default 1). |
| updated_since | string Example: updated_since=2026-10-01T00:00:00Z Sync mode: only rows whose |
| cursor | string Sync mode: the |
{- "status": true,
- "message": "string",
- "result": [
- {
- "guid": "string",
- "number": "string",
- "name": "string",
- "status": 0,
- "start_time": "string",
- "total_time": 0,
- "qty_invoice": 0,
- "unit_price": "string",
- "amount": "string",
- "invoiced_amount": "string",
- "outstanding_amount": "string",
- "estimated_amount": "string",
- "item": null,
- "customer": {
- "guid": "5d1e2c4a-8b7f-11ef-9c3a-0242ac120002",
- "name": "Byggir ehf.",
- "registration_no": "4602070880",
- "email": "bokhald@byggir.is",
- "output_select": 3,
- "trading_partner_id": "",
- "address": "Lækjargata 4",
- "zip": "101",
- "city": "Reykjavík",
- "phone_number": "",
- "vat": "",
- "lang": "is",
- "currency": "ISK",
- "tax_exempt": 0,
- "term": "",
- "due_date": 3,
- "settlement_date": 7,
- "photo": "",
- "updated_timestamp": "2026-10-12"
}, - "invoices": [
- {
- "guid": "string",
- "number": "string",
- "type": "invoice",
- "status": "string",
- "amount": "string",
- "currency": "string",
- "exchange_rate": 0,
- "created_date": "string",
- "issue_date": "string",
- "due_date": "string",
- "settlement_date": "string",
- "paid_date": "string",
- "delivery_date": "string",
- "description": "string",
- "booking": "string",
- "cost_provide": "string",
- "terms": "string",
- "refer_guid": "string",
- "updated_timestamp": "string",
- "accounting_status": "string",
- "accounting_message": "string",
- "claim_id": "string",
- "claim_status": "",
- "collection_cost": 0,
- "other_default_costs_amount": 0,
- "default_charge_amount": 0,
- "default_interest_amount": 0,
- "capital_gains_tax": 0,
- "bank_transaction_amount": "string",
- "xml_status": "string",
- "project_guid": "string",
- "project_number": "string",
- "show_project_link": true,
- "customer": {
- "guid": "string",
- "name": "string",
- "address": "string",
- "zip": "string",
- "city": "string",
- "registration_no": "string",
- "email": "string"
}, - "items": [
- {
- "guid": "string",
- "item_number": "string",
- "description": "string",
- "qty": "string",
- "uom": "string",
- "unit_price": "string",
- "discount": 0,
- "discount_type": 0,
- "tax": "string",
- "vat": 0,
- "vat_amount": "string"
}
], - "total_24vat": "string",
- "total_11vat": "string",
- "total_0vat": "string"
}
], - "logs": [
- {
- "guid": "0f8e2c1a-6b1d-11f1-9a5e-0242ac120002",
- "task_guid": "614669f6-3560-11e7-8d19-408d5c6208bc",
- "date": "2026-10-14",
- "end_date": "",
- "quantity": 1.5,
- "description": "Uppsetning á vef",
- "manual": 1,
- "advanced": 0,
- "count_of_workers": 0,
- "hours_worked_per_day": 0,
- "creation_date": "14.10.2026",
- "from_date": "",
- "to_date": "",
- "image": "",
- "external_ref": "OPS-4711-L1",
- "version": 1,
- "updated_at": "2026-10-14 09:12:44",
- "deleted_at": ""
}
], - "canStart": true,
- "canStop": true,
- "canDeActive": true,
- "project_name": "string",
- "project_guid": "string",
- "project_number": "string",
- "external_ref": "string",
- "version": 0,
- "created_at": "string",
- "updated_at": "string"
}
], - "limit": 0,
- "has_more": true,
- "next_cursor": "string"
}A task for a customer, billed with a catalogue item (item.guid) or a
new item described inline — the inline item is added to the catalogue.
item is required.
If external_ref matches an existing task, nothing is created: the
answer is that task's guid with existing: true and the task in task.
Otherwise result is the new task's guid, plus its version.
A refusal is HTTP 200 with status: false and e.g. Customer is required, Item is required, No project found, Customer does not match the project customer, Project name is required., an item error
(Description is required, Unit of measure is required, Tax is required), estimated_amount must be a non-negative number, Data task invalidate, or error_code invalid_external_ref / feature_required.
| Idempotency-Key | string [ 1 .. 128 ] characters Example: 7c1f0d2e-ops-4711 Optional on any write. A retry with the same key and the same request
(path and body) replays the stored response — same HTTP status, plus the
header |
required | string or TaskCreate (object) JSON-encoded TaskCreate object (or the object itself). |
{- "data": "{\"customer_guid\":\"5d1e2c4a-8b7f-11ef-9c3a-0242ac120002\",\"name\":\"Uppsetning\",\"item\":{\"guid\":\"43521ec8-3413-11e7-b148-408d5c6208bc\"},\"external_ref\":\"OPS-4711-T1\"}"
}{- "status": true,
- "message": "string",
- "result": "string",
- "version": 0,
- "existing": true,
- "task": {
- "guid": "string",
- "number": "string",
- "name": "string",
- "status": 0,
- "start_time": "string",
- "total_time": 0,
- "qty_invoice": 0,
- "unit_price": "string",
- "amount": "string",
- "invoiced_amount": "string",
- "outstanding_amount": "string",
- "estimated_amount": "string",
- "item": null,
- "customer": {
- "guid": "5d1e2c4a-8b7f-11ef-9c3a-0242ac120002",
- "name": "Byggir ehf.",
- "registration_no": "4602070880",
- "email": "bokhald@byggir.is",
- "output_select": 3,
- "trading_partner_id": "",
- "address": "Lækjargata 4",
- "zip": "101",
- "city": "Reykjavík",
- "phone_number": "",
- "vat": "",
- "lang": "is",
- "currency": "ISK",
- "tax_exempt": 0,
- "term": "",
- "due_date": 3,
- "settlement_date": 7,
- "photo": "",
- "updated_timestamp": "2026-10-12"
}, - "invoices": [
- {
- "guid": "string",
- "number": "string",
- "type": "invoice",
- "status": "string",
- "amount": "string",
- "currency": "string",
- "exchange_rate": 0,
- "created_date": "string",
- "issue_date": "string",
- "due_date": "string",
- "settlement_date": "string",
- "paid_date": "string",
- "delivery_date": "string",
- "description": "string",
- "booking": "string",
- "cost_provide": "string",
- "terms": "string",
- "refer_guid": "string",
- "updated_timestamp": "string",
- "accounting_status": "string",
- "accounting_message": "string",
- "claim_id": "string",
- "claim_status": "",
- "collection_cost": 0,
- "other_default_costs_amount": 0,
- "default_charge_amount": 0,
- "default_interest_amount": 0,
- "capital_gains_tax": 0,
- "bank_transaction_amount": "string",
- "xml_status": "string",
- "project_guid": "string",
- "project_number": "string",
- "show_project_link": true,
- "customer": {
- "guid": "string",
- "name": "string",
- "address": "string",
- "zip": "string",
- "city": "string",
- "registration_no": "string",
- "email": "string"
}, - "items": [
- {
- "guid": "string",
- "item_number": "string",
- "description": "string",
- "qty": "string",
- "uom": "string",
- "unit_price": "string",
- "discount": 0,
- "discount_type": 0,
- "tax": "string",
- "vat": 0,
- "vat_amount": "string"
}
], - "total_24vat": "string",
- "total_11vat": "string",
- "total_0vat": "string"
}
], - "logs": [
- {
- "guid": "0f8e2c1a-6b1d-11f1-9a5e-0242ac120002",
- "task_guid": "614669f6-3560-11e7-8d19-408d5c6208bc",
- "date": "2026-10-14",
- "end_date": "",
- "quantity": 1.5,
- "description": "Uppsetning á vef",
- "manual": 1,
- "advanced": 0,
- "count_of_workers": 0,
- "hours_worked_per_day": 0,
- "creation_date": "14.10.2026",
- "from_date": "",
- "to_date": "",
- "image": "",
- "external_ref": "OPS-4711-L1",
- "version": 1,
- "updated_at": "2026-10-14 09:12:44",
- "deleted_at": ""
}
], - "canStart": true,
- "canStop": true,
- "canDeActive": true,
- "project_name": "string",
- "project_guid": "string",
- "project_number": "string",
- "external_ref": "string",
- "version": 0,
- "created_at": "string",
- "updated_at": "string"
}
}Takes the list's filters except paging.
| type | string Default: "open" Enum: "open" "invoice" "older" "all" Default |
| project_guid | string |
| customer_guid | string |
| external_ref | string <= 128 characters |
| include_removed | string Default: "0" Enum: "0" "1"
|
| updated_since | string Only tasks modified at or after this time (see the list). |
{- "status": true,
- "message": "string",
- "result": 42
}Archived tasks are returned too (status 2). Each log entry carries the task-LOG guid needed by the log edit/delete endpoints.
| guid required | string The resource's GUID. |
{- "status": true,
- "message": "string",
- "result": {
- "guid": "string",
- "number": "string",
- "name": "string",
- "status": 0,
- "start_time": "string",
- "total_time": 0,
- "qty_invoice": 0,
- "unit_price": "string",
- "amount": "string",
- "invoiced_amount": "string",
- "outstanding_amount": "string",
- "estimated_amount": "string",
- "item": null,
- "customer": {
- "guid": "5d1e2c4a-8b7f-11ef-9c3a-0242ac120002",
- "name": "Byggir ehf.",
- "registration_no": "4602070880",
- "email": "bokhald@byggir.is",
- "output_select": 3,
- "trading_partner_id": "",
- "address": "Lækjargata 4",
- "zip": "101",
- "city": "Reykjavík",
- "phone_number": "",
- "vat": "",
- "lang": "is",
- "currency": "ISK",
- "tax_exempt": 0,
- "term": "",
- "due_date": 3,
- "settlement_date": 7,
- "photo": "",
- "updated_timestamp": "2026-10-12"
}, - "invoices": [
- {
- "guid": "string",
- "number": "string",
- "type": "invoice",
- "status": "string",
- "amount": "string",
- "currency": "string",
- "exchange_rate": 0,
- "created_date": "string",
- "issue_date": "string",
- "due_date": "string",
- "settlement_date": "string",
- "paid_date": "string",
- "delivery_date": "string",
- "description": "string",
- "booking": "string",
- "cost_provide": "string",
- "terms": "string",
- "refer_guid": "string",
- "updated_timestamp": "string",
- "accounting_status": "string",
- "accounting_message": "string",
- "claim_id": "string",
- "claim_status": "",
- "collection_cost": 0,
- "other_default_costs_amount": 0,
- "default_charge_amount": 0,
- "default_interest_amount": 0,
- "capital_gains_tax": 0,
- "bank_transaction_amount": "string",
- "xml_status": "string",
- "project_guid": "string",
- "project_number": "string",
- "show_project_link": true,
- "customer": {
- "guid": "string",
- "name": "string",
- "address": "string",
- "zip": "string",
- "city": "string",
- "registration_no": "string",
- "email": "string"
}, - "items": [
- {
- "guid": "string",
- "item_number": "string",
- "description": "string",
- "qty": "string",
- "uom": "string",
- "unit_price": "string",
- "discount": 0,
- "discount_type": 0,
- "tax": "string",
- "vat": 0,
- "vat_amount": "string"
}
], - "total_24vat": "string",
- "total_11vat": "string",
- "total_0vat": "string"
}
], - "logs": [
- {
- "guid": "0f8e2c1a-6b1d-11f1-9a5e-0242ac120002",
- "task_guid": "614669f6-3560-11e7-8d19-408d5c6208bc",
- "date": "2026-10-14",
- "end_date": "",
- "quantity": 1.5,
- "description": "Uppsetning á vef",
- "manual": 1,
- "advanced": 0,
- "count_of_workers": 0,
- "hours_worked_per_day": 0,
- "creation_date": "14.10.2026",
- "from_date": "",
- "to_date": "",
- "image": "",
- "external_ref": "OPS-4711-L1",
- "version": 1,
- "updated_at": "2026-10-14 09:12:44",
- "deleted_at": ""
}
], - "canStart": true,
- "canStop": true,
- "canDeActive": true,
- "project_name": "string",
- "project_guid": "string",
- "project_number": "string",
- "external_ref": "string",
- "version": 0,
- "created_at": "string",
- "updated_at": "string"
}
}Changes a task's name, estimate, external reference or project. Put only
the fields to change in data (a JSON-encoded string, or a nested
object); omitted fields are left as they are. PUT bodies must be
application/json.
project_guid moves the task to another project of the same
customer, or unlinks it with "". It needs the Projects add-on (also
to unlink), and an invoiced task cannot change project (HTTP 409
task_invoiced).external_ref must be unique across the account's tasks (HTTP 409
external_ref_exists); "" clears it.version (inside data, or at the top level) makes the write
conditional: if the task has changed since that version the update is
refused with HTTP 409 version_conflict and current_version. Without
it the write is unconditional.Archived tasks cannot be updated (No task found). Returns the updated
task, in the same shape as GET /api/v1/agent/tasks/{guid}.
| guid required | string The resource's GUID. |
| Idempotency-Key | string [ 1 .. 128 ] characters Example: 7c1f0d2e-ops-4711 Optional on any write. A retry with the same key and the same request
(path and body) replays the stored response — same HTTP status, plus the
header |
required | string or TaskUpdate (object) JSON-encoded TaskUpdate object (a nested object is also accepted). Must contain at least one field. |
| version | integer >= 1 Alternative to |
{- "data": "{\"name\":\"Uppsetning – áfangi 2\",\"estimated_amount\":250000,\"external_ref\":\"OPS-4711-T2\",\"version\":3}"
}{- "status": true,
- "message": "string",
- "result": null
}Starts the timer of a stopped, not yet invoiced task (status 0 → 1). Anything else — a running, archived or invoiced task, or an unknown guid — answers status: false, No task found.
| guid required | string The resource's GUID. |
| Idempotency-Key | string [ 1 .. 128 ] characters Example: 7c1f0d2e-ops-4711 Optional on any write. A retry with the same key and the same request
(path and body) replays the stored response — same HTTP status, plus the
header |
{- "status": true,
- "message": "string",
- "result": null
}Stops the timer and logs the hours since it was started (2 decimals) as
a timer entry dated today. result is that entry. With adv: 1 the
quantity is (days from date to today, inclusive) × p × h instead.
The server does not check that the timer is running: on a stopped task
it logs the time since the last start. Call it only after
POST …/start. An invoiced task, or an unknown guid, answers
status: false, No task found.
| guid required | string The resource's GUID. |
| Idempotency-Key | string [ 1 .. 128 ] characters Example: 7c1f0d2e-ops-4711 Optional on any write. A retry with the same key and the same request
(path and body) replays the stored response — same HTTP status, plus the
header |
| description | string Note on the entry. |
| external_ref | string <= 128 characters Your own reference for the entry. Must be unique within the task. |
| adv | integer Enum: 0 1
|
| date | string <date> Advanced mode: the first day of the range (the last is today). |
| p | integer Advanced mode: number of workers. |
| h | integer Advanced mode: hours per day. |
{- "description": "string",
- "external_ref": "string",
- "adv": 0,
- "date": "2019-08-24",
- "p": 0,
- "h": 0
}{- "status": true,
- "message": "string",
- "result": {
- "guid": "0f8e2c1a-6b1d-11f1-9a5e-0242ac120002",
- "task_guid": "614669f6-3560-11e7-8d19-408d5c6208bc",
- "date": "2026-10-14",
- "end_date": "",
- "quantity": 1.5,
- "description": "Uppsetning á vef",
- "manual": 1,
- "advanced": 0,
- "count_of_workers": 0,
- "hours_worked_per_day": 0,
- "creation_date": "14.10.2026",
- "from_date": "",
- "to_date": "",
- "image": "",
- "external_ref": "OPS-4711-L1",
- "version": 1,
- "updated_at": "2026-10-14 09:12:44",
- "deleted_at": ""
}
}Sets status 2 (archived); the task leaves the lists unless include_removed=1. An invoiced or already archived task answers status: false, No task found.
| guid required | string The resource's GUID. |
| Idempotency-Key | string [ 1 .. 128 ] characters Example: 7c1f0d2e-ops-4711 Optional on any write. A retry with the same key and the same request
(path and body) replays the stored response — same HTTP status, plus the
header |
{- "status": true,
- "message": "string",
- "result": null
}Takes the task-LOG entry's guid (from a task's logs or
GET /tasks/logs), not the task's guid. Fields are sent flat, like
POST /tasks/log, and the edit is a full replacement: qty and
end_date are required, and an omitted description, adv, p or h
is cleared. The entry becomes a manual entry dated date, and the
task's total moves by the difference. result is the updated entry.
Send version to make the edit conditional (HTTP 409
version_conflict with current_version if the entry changed since).
A refusal is status: false with No task log found, Please input quantity, Please input end date or Please input start date
(advanced mode).
| Idempotency-Key | string [ 1 .. 128 ] characters Example: 7c1f0d2e-ops-4711 Optional on any write. A retry with the same key and the same request
(path and body) replays the stored response — same HTTP status, plus the
header |
| guid required | string Task-LOG entry guid. |
| version | integer >= 1 The entry's version as you last read it. |
| qty required | number or string Quantity in the task item's unit — normally hours. Must be greater than 0; a decimal comma is accepted ( |
| date required | string <date> Entry date, |
| end_date required | string <date>
|
| description | string |
| adv | integer Default: 0 Enum: 0 1
|
| p | integer >= 1 Advanced mode: number of workers. Use a whole number. |
| h | integer >= 1 Advanced mode: hours worked per day. Use a whole number — the entry stores |
| external_ref | string <= 128 characters Your own reference for the entry. Must be unique within the task. |
{- "guid": "0f8e2c1a-6b1d-11f1-9a5e-0242ac120002",
- "qty": 2,
- "date": "2026-10-14",
- "end_date": "2026-10-14",
- "description": "Uppsetning á vef",
- "version": 1
}{- "status": true,
- "message": "string",
- "result": {
- "guid": "0f8e2c1a-6b1d-11f1-9a5e-0242ac120002",
- "task_guid": "614669f6-3560-11e7-8d19-408d5c6208bc",
- "date": "2026-10-14",
- "end_date": "",
- "quantity": 1.5,
- "description": "Uppsetning á vef",
- "manual": 1,
- "advanced": 0,
- "count_of_workers": 0,
- "hours_worked_per_day": 0,
- "creation_date": "14.10.2026",
- "from_date": "",
- "to_date": "",
- "image": "",
- "external_ref": "OPS-4711-L1",
- "version": 1,
- "updated_at": "2026-10-14 09:12:44",
- "deleted_at": ""
}
}Adds a manual time entry to a task and returns it. Fields are sent
flat at the top level (no data wrapper), as JSON — or as
multipart/form-data to attach a file.
Two modes:
qty units (normally hours) on date. end_date is
still required; send the same day as date.adv: 1) — a date range worked by a crew. The logged
quantity is computed as (days from date to end_date, inclusive) ×
p (workers) × h (hours per day); send both p and h, or the
entry is logged as 0. qty must still be a positive number — it is
replaced by the computed value.The task's total grows by the logged quantity. A task that has already
been invoiced takes no new entries (the reply is No task found).
| Idempotency-Key | string [ 1 .. 128 ] characters Example: 7c1f0d2e-ops-4711 Optional on any write. A retry with the same key and the same request
(path and body) replays the stored response — same HTTP status, plus the
header |
| guid required | string The task's GUID (not a time-entry GUID). |
| qty required | number or string Quantity in the task item's unit — normally hours. Must be greater than 0; a decimal comma is accepted ( |
| date required | string <date> Entry date, |
| end_date required | string <date>
|
| description | string |
| adv | integer Default: 0 Enum: 0 1
|
| p | integer >= 1 Advanced mode: number of workers. Use a whole number. |
| h | integer >= 1 Advanced mode: hours worked per day. Use a whole number — the entry stores |
| external_ref | string <= 128 characters Your own reference for the entry. Must be unique within the task. |
{- "guid": "614669f6-3560-11e7-8d19-408d5c6208bc",
- "qty": 1.5,
- "date": "2026-10-14",
- "end_date": "2026-10-14",
- "description": "Uppsetning á vef",
- "external_ref": "OPS-4711-L1"
}{- "status": true,
- "message": "string",
- "result": {
- "guid": "0f8e2c1a-6b1d-11f1-9a5e-0242ac120002",
- "task_guid": "614669f6-3560-11e7-8d19-408d5c6208bc",
- "date": "2026-10-14",
- "end_date": "",
- "quantity": 1.5,
- "description": "Uppsetning á vef",
- "manual": 1,
- "advanced": 0,
- "count_of_workers": 0,
- "hours_worked_per_day": 0,
- "creation_date": "14.10.2026",
- "from_date": "",
- "to_date": "",
- "image": "",
- "external_ref": "OPS-4711-L1",
- "version": 1,
- "updated_at": "2026-10-14 09:12:44",
- "deleted_at": ""
}
}Takes the task-LOG entry's guid, not the task's guid. The entry's
quantity is taken off the task's total and the entry is removed; it
cannot be restored, but GET /tasks/logs?include_removed=1 still lists
it with deleted_at set so a sync sees it go. result is the entry's
guid; an unknown guid answers status: false, No task log found.
Send version (query or JSON body) to make the delete conditional.
| guid required | string Task-LOG entry guid. |
| version | integer >= 1 The entry's version as you last read it. A stale value is refused with HTTP 409 |
| Idempotency-Key | string [ 1 .. 128 ] characters Example: 7c1f0d2e-ops-4711 Optional on any write. A retry with the same key and the same request
(path and body) replays the stored response — same HTTP status, plus the
header |
{- "status": true,
- "message": "string",
- "result": "614669f6-3560-11e7-8d19-408d5c6208bc"
}Time entries (task logs) across all of the account's tasks, archived tasks included. Two ways to page:
limit (default 50,
max 500) and page. The response carries total, page and limit.updated_since and/or cursor. Entries come in
(updated_at, id) order, limit defaults to 100 (max 500), and the
response carries has_more and next_cursor: pass next_cursor back
as cursor until has_more is false. page is ignored; the other
filters still apply. Add include_removed=1 to also receive deleted
entries (deleted_at set).from_date / to_date filter on the entry date (date) and must be
Y-m-d — anything else returns status: false,
Field from_date must be format Y-m-d.
| task_guid | string Only entries of this task. An unknown GUID returns |
| project_guid | string Only entries of tasks in this project. An unknown GUID returns |
| external_ref | string <= 128 characters Exact match on the entry's |
| from_date | string <date> Start date (YYYY-MM-DD). |
| to_date | string <date> End date (YYYY-MM-DD). |
| include_removed | string Default: "0" Enum: "0" "1"
|
| updated_since | string Example: updated_since=2026-10-01T00:00:00Z Sync mode: only rows whose |
| cursor | string Sync mode: the |
| limit | integer [ 1 .. 500 ] Page size — default 50 in page mode, 100 in sync mode; capped at 500. |
| page | integer >= 1 Default: 1 Page number (page mode only). |
{- "status": true,
- "message": "string",
- "result": [
- {
- "guid": "0f8e2c1a-6b1d-11f1-9a5e-0242ac120002",
- "task_guid": "614669f6-3560-11e7-8d19-408d5c6208bc",
- "date": "2026-10-14",
- "end_date": "",
- "quantity": 1.5,
- "description": "Uppsetning á vef",
- "manual": 1,
- "advanced": 0,
- "count_of_workers": 0,
- "hours_worked_per_day": 0,
- "creation_date": "14.10.2026",
- "from_date": "",
- "to_date": "",
- "image": "",
- "external_ref": "OPS-4711-L1",
- "version": 1,
- "updated_at": "2026-10-14 09:12:44",
- "deleted_at": ""
}
], - "total": 0,
- "page": 0,
- "limit": 0,
- "has_more": true,
- "next_cursor": "string"
}Read-only, newest first, always paged (10 per page by default). type is a number: 0 standard item, 1 subscription, 2 donation, 3 coupon, 4 event. Only event sales have attendees.
| search_text | string Substring of the product name. |
| limit | integer >= 1 Default: 10 Page size (default 10). |
| page | integer Default: 1 Page number (default 1). |
{- "status": true,
- "message": "string",
- "result": [
- {
- "guid": "string",
- "name": "string",
- "description": "string",
- "type": 0,
- "status": 0,
- "is_open": true,
- "url": "string",
- "terms": "string",
- "amount": 0,
- "inventory_control": true,
- "inventory_count": 0
}
], - "total": 0,
- "page": 0
}One row per attendee. Paging (10 per page by default) runs over the
purchases, not the attendees, and total counts purchases — one purchase
can carry several attendees. Refused with status: false: No selling found (unknown guid) or This selling is not an event (type other
than 4).
| guid required | string The resource's GUID. |
| limit | integer >= 1 Default: 10 Page size (default 10). |
| page | integer Default: 1 Page number (default 1). |
{- "status": true,
- "message": "string",
- "result": [
- {
- "attendee": "string",
- "attended": "true",
- "qty": 0,
- "message": "string",
- "fields": [
- {
- "label": "string",
- "value": "string"
}
], - "invoice_number": "string",
- "invoice_status": "string",
- "name": "string",
- "kennitala": "string",
- "phone_number": "string",
- "address": "string",
- "zip": "string",
- "city": "string"
}
], - "total": 0,
- "page": 0
}