# Invoicing

NOTE This is work in progress so please ask questions and give feedback to us so we can improve the documentation and the API through the Slack channel you've been/will be invited to.

# Prerequisites

To use the invoice creation endpoint you need an oauth token. See oauth-flow.

# Create invoice request

A POST request to the /v2/invoices endpoint creates a new invoice

Row unit prices need to be expressed in the money format. The parameter user_confirmed_work_in_finland is required to be true if the client country is not FI.

Fields:

  • client_type

    • COMPANY or PERSON
  • business_id

    • required when client_type is COMPANY
  • company_name

    • required when client_type is COMPANY
  • description

    • Required when autocollect is set true. The description of the done work must be on the invoice. Just "work" or list of targets/addresses is not descriptive enough. The description has to tell both the client and the person processing the invoice what work is being invoiced.
  • notify_overdue_and_automatic_debt_collection

    • When true UKKO.fi takes care of invoice follow-up, overdue notices and debt collection.
    • Was previously autocollect. This works as well but is deprecated
  • vat_rate

    • The vat_rate parameter is required to be "VAT_REGULAR" for 24% vat.
  • industry

    • The line of work being invoiced
    • NOTE: This requires a mapping between your line of work lists and UKKO.fi lists.
    • NOTE: Also note that jobs requiring permits need to be handled with great scrutiny on our end as some work are not allowed to be invoiced through UKKO.fi.
  • term_of_payment

    • minimum 14 days for person client
    • minimum 7 days for company client when autocollect is false, otherwise 14 days
  • einvoice_address

    • required if the delivery_method is set to EINVOICE
  • rows

    • short_description
      • Required
    • contains_vat
      • When true it is assumed the the unit price contains the vat
    • unit_type
      • is PIECE or HOUR
    • unit_price
      • IMPORTANT: This is handled as fractions of cents and not as cents as everything else

# Example request:

{
  "company_name": "string",
  "contact_person": "string",
  "client_type": "COMPANY",
  "language": "FI",
  "street_address1": "string",
  "zip_code": "string",
  "city": "string",
  "country": "string",
  "business_id": "string",
  "email": "user@example.com",
  "clients_reference": "string",
  "description": "string",
  "industry": 1,
  "user_confirmed_work_in_finland": false,
  "vat_rate": "VAT_REGULAR",
  "rows": [
    {
      "short_description": "string",
      "quantity": "10.00",
      "unit_price": {
        "amount": "20000",
        "currency": "EUR"
      },
      "contains_vat": true,
      "unit_type": "PIECE",
      "start_date": "string",
      "end_date": "string"
    }
  ]
}

# Example response:

{
  "data": {
    "id": 1,
    "company_name": "string",
    "contact_person": "string",
    "client_type": "COMPANY",
    "language": "FI",
    "email": "user@example.com",
    "street_address1": "string",
    "zip_code": "string",
    "city": "string",
    "country": "string",
    "business_id": "string",
    "clients_reference": "string",
    "description": "string",
    "industry": {
      "id": 1,
      "industry_id": "001",
      "name": "string",
      "subcategories": {}
    },
    "user_confirmed_work_in_finland": false,
    "vat_rate": "VAT_REGULAR",
    "term_of_payment": 14,
    "due_date": "2020-01-15",
    "reference_number": "1234567",
    "barcode": "4301237300012305600120000000000000000000012345674200213",
    "created_at": "2020-01-01"
    "rows": [{
      "id": 1,
      "invoice_id": 1,
      "short_description": "string",
      "start_date": "string",
      "end_date": "string",
      "quantity": 1,
      "unit_type": "PIECE",
      "unit_price": {
        "amount": "20000",
        "currency": "EUR"
      },
      "contains_vat": true,
      "total_no_vat": {
        "amount": "2000",
        "currency": "EUR"
      },
      "vat_percent": 0,
      "vat_sum": {
        "amount": "2000",
        "currency": "EUR"
      },
      "total_sum": {
        "amount": "2000",
        "currency": "EUR"
      },
      "row_type": null
    }],
    "can": {
          "create": {
            "allowed": true,
          },
          "send": {
            "allowed": false,
            "reasons": [
              "terms_of_service_not_signed",
              "strong_identification_missing"
            ]
          },
        }
  }
}

More details on the different request and return parameters can be found in the the Swagger documentation.

# Sending a created invoice to processing

# Send to processing request

A POST request to /v2/invoices/{invoice_id}/processing sends to specified invoice to UKKO.fi administration for processing. The endpoint returns 204 http-status code on success. Only an invoice that is in the DRAFT state can be sent to processing. Newly created invoices and rejected invoices are in the DRAFT state. You will need to send a query parameter accept_terms_of_service to indicate that the user has accepted UKKO.fi terms of service before sending the invoice to processing. You must show the terms for the user before you can allow them to accept the terms. See Terms of Service API

# Example request

POST https://[UKKO_HOST]/v2/invoices/12345/processing?accept_terms_of_service=true`

# What Happens If the Sent Invoice Gets Discarded or Rejected

One of the benefits of using UKKO.fi is that our trained financial admins manually check and validate every invoice before sending them to the invoicing and accounting. This means that the invoice may get rejected (sent back to the user for fixes or for additional information) or discarded (thrown away completely) with an explanation message, why the invoice was rejected/discarded.

Currently this means for integration partners that the invoice gets discarded with message telling the user to fix the invoice in your service or application by creating new invoice and sending it as new invoice.

Later on there will be webhooks for getting updated about invoice status changes and discards/rejects.

# Money values in requests

We're internally handling money values as integer cents (5 EUR * 100) and the API must receive money fields as following for money fields in requests

{
  "amount": "5000000",
  "currency": "EUR"
}

Please note that the field Invoice.rows[...].unit_price is inputted and outputted as fractions of cents, e.g. 5 EUR * 1000 = 5 000 as there are cases where the additional precision is required for this field.

# Policy failures

NOTE: If these are not clear enough, please consult UKKO.fi API support for better descriptions:

  • strong_identification_missing
  • terms_of_service_not_signed
  • missing_country_of_living
  • country_of_living_not_allowed
  • ssn_missing
  • strong_identification_missing
  • strong_identification_expired
  • too_young
  • guardians_approval_required
  • nationality_not_set
  • has_no_work_permit
  • work_permit_not_valid_yet
  • work_permit_expired
  • has_no_valid_id_document

# Terms of Service API

To allow for invoicing a user has to have accepted the UKKO.fi terms of service. To get the current terms of service you can use the terms of service API. The terms of service is available with the following language codes: fi, et, en, sv and ru.

# Example request

GET https://[UKKO_HOST]/v2/system/service-agreements/terms-of-service?language=fi

# Example response

{
  "data": {
    "terms": "<h2>UKKO.fi-palvelun k&auml;ytt&ouml;ehdot</h2>...",
    "type": "terms-of-service",
    "language": "fi",
    "published_at": "2020-03-03T12:44:30+02:00"
  }
}