Amili Docs
Home
Products
Products
  • Debt.collection
  • Account Receivable
  • Distribution
  • Pay
Go to amili.no
Home
Products
Products
  • Debt.collection
  • Account Receivable
  • Distribution
  • Pay
Go to amili.no
  1. Pay
  • Home
    • Welcome to Amili Docs
    • Responsible disclosure
    • Become a partner
  • Debt Collection
    • About the AutoCollect API
    • Getting started with the AutoCollect API
    • Webhooks
    • Example Workflow
    • Batches
      • GetBatchById
      • GetBatchesByOrganization
      • GetBatchById - Legacy (To be removed)
    • Collections
      • GetCasesByOrganization
      • AcceptDebtCollectionList
      • RejectDebtCollectionList
      • PauseCase
      • WithdrawCase
      • ResumeCase
      • AcceptEvictionRequest
      • RejectEvictionRequest
      • AcceptEvictionConfirmation
      • RejectEvictionConfirmation
    • Correction
      • CreateCorrections
    • Invoice
      • CreateInvoices
      • GetInvoicesByOrganization
      • GetInvoiceById
    • Payment
      • CreatePayments
    • Settlement
      • GetSettlements
      • GetSettlement on Id
    • AutoCollect Legacy API
      • Attachment
        • /webapi/api/Attachment
      • Batch
        • /webapi/api/Batch
        • /webapi/api/Batch
      • Ping
        • /webapi/api/Ping
    • ErrorHandling
      • How to
      • Codes
        • DUPLICATE_UNIQUE_SOURCE_PAYMENT_ID
  • Accounts Receivable
    • Actions
      • POST (create) an action
      • POST (create) a reports action/generate a report
    • ArItems
      • GET a list of AR items
      • PUT (update) ar item details
      • GET one AR item
    • AutoPostings
      • POST (create) one or more auto postings
    • Batches
      • GET one batch
    • ClientConfigs
      • GET a list of client config values
      • GET values for one client config key
    • Codes
      • GET ARM system code values
    • Customers
      • POST (create) one customer
      • PUT (update) one customer
      • GET a list of customers
      • GET one customer
      • DELETE a customer
      • POST (create) a batch of customers
      • PUT (update) a batch of customers
    • DocumentBundles
      • GET a list of document bundles
      • GET one document bundle
    • Documents
      • POST (create) one document
      • GET a list of documents
      • GET one document
      • POST (create) a batch of documents
    • Files
      • GET one or more OS files
      • POST (upload) one or more OS files
      • GET one OS file
    • GlItems
      • Get one GL item
      • GET a list of GL items
    • GlMovements
      • Get movement/balance for the latest closed GL year/period
      • GET a list of GL movements/balances
    • Insights
      • GET a list of ADB intervals
    • LogItems
      • GET one log item
      • GET a list of log items
    • PaymentReservations
      • POST (create) a new payment reservation
    • Health
      • Check API health
  • Pay
    • AmiliPay API Introduction
    • Industry Categories Reference
    • Webhooks Reference
    • Merchant
      • List all customers
      • Create customer
      • Retrieve customer
      • Update customer
      • Create customer token
      • Retrieve pricing for a merchant
      • Update pricing for a merchant
      • List a customer's accepted agreements
    • User
      • List all users
      • Create user
      • Retrieve user
      • Update user
      • Delete user
    • Onboarding
      • Create onboarding application
      • Retrieve onboarding application
      • Update onboarding application
      • Delete onboarding application
      • Start processing onboarding
      • Delete onboarding shareholder
      • Create onboarding document
      • Retrieve onboarding document
      • Delete onboarding document
      • Retrieve available account agreements
      • Create onboarding agreement
      • Mark selected agreement as an accepted by the account
      • Retrieve a single agreement
      • Update onboarding agreement
      • Deactivate agreement
    • Invoice
      • List all invoices
      • Create invoice
      • Retrieve invoice
      • Update invoice
      • Delete invoice
      • Refund invoice
    • Transactions
      • Get invoice transactions
    • Payout
      • List all payouts
      • Retrieve payout
      • Retrieve payout details
    • Product lines classification
      • Upload a CSV file
      • Manually get processed CSV file path
      • Download a previously uploaded CSV file
  1. Pay

AmiliPay API Introduction

This is the API documentation for managing the AmiliPay service.

Endpoint#

We only allow HTTPS connections. Regular HTTP connections will be redirected to HTTPS. We have two environments:
EnvironmentBase URL
Productionhttps://api.amili.no/internal/pay2/external/api/v1/
Testinghttps://pay-qa.amili.no/external/api/v1/
Build and test your integration against the testing environment first, then switch to production once you're ready to go live. The two are separate accounts/data stores - a customer, invoice, or token created in testing does not exist in production and vice versa.

Allowed HTTP requests#

GET: Get a resource or list of resources
POST: Create a resource
PUT: Update a resource
DELETE: Delete a resource

Headers#

Send these headers with every request:
Accept: application/json
Content-Type: application/json (for requests with a body)

Authentication#

Authenticate with a partner API key. Create and manage keys under Settings > Partner API Tokens (up to 10 active keys per account, each with its own scopes). Send the key on every request using one of:
X-API-KEY: {token}
Authorization: ApiKey {token}
Authorization: Bearer {token} (recognized only when the token itself is prefixed apk_)
A key is not gated on the onboarding progress of any merchant you manage - it works regardless of how far along a given merchant's onboarding is. It is gated on the lifecycle status of the key's own owning account: a key belonging to a Suspended or Deactivated account stops authenticating.
To act on behalf of a specific merchant you've onboarded (e.g. from your own backend), you can also mint a merchant-scoped token via POST /customers/{account_id}/tokens - see Reference > Merchant.

Rate Limiting#

You can make 450 requests every minute per API key (per IP if unauthenticated). Responses include X-RateLimit-Limit and X-RateLimit-Remaining headers; exceeding the limit returns 429 with a Retry-After header.

Integration flow#

1. Onboard the merchant#

A merchant must complete onboarding and accept the current agreement(s) before you can create invoices for them. Call POST /customers to create the merchant account - this automatically creates an onboarding record and returns an account_id plus an onboarding_token.
Hosted onboarding (recommended): hand the customer the onboarding_token and embed our onboarding widget - it walks them through agreement approval and KYC data collection.
Self-hosted onboarding: collect agreement approval and KYC data yourself and submit it against the onboarding record that was already created for you - PUT /onboardings/{id} (do not POST a new one, that creates a duplicate) plus POST /onboardings/{id}/documents - then call POST /onboardings/{id}/process to submit it for review.
Track progress with the ONBOARDING_STATUS_UPDATED webhook; a merchant can accept payments once its status is COMPLETED.

2. Create a payment request#

Create an invoice with POST /invoices. A merchant token creates the invoice under its own account; a partner token must supply account_id to target one of its direct-child merchants - a partner cannot create an invoice without specifying which child merchant it belongs to. Required fields: amount, invoice_id, customer_id (your own reference for the payer - unrelated to the merchant's account_id), name, currency, due_date. Optionally supply customer_reference - your own free-text reference for the payer, up to 255 characters, stored and returned as-is. Set notify_customer: true (default) together with email/phone to have us notify the payer directly, or use the redirect_url returned in the response to send them to the payment page yourself.

3. Handle webhooks#

Register a webhook endpoint from the merchant/partner dashboard under Settings > Webhooks - enter your callback_url, choose which events to subscribe to, and save; this returns a signing secret used to verify deliveries. There is no partner-API endpoint for registering or managing webhook endpoints today - it's dashboard-only, not something you can automate from your own backend. We POST every event to your callback_url; your endpoint must return a 2xx status, or we retry after 1, then 5, 15, and 60 minutes (4 attempts total).
See the Webhooks reference for the full, current list of event types - it includes invoice events (INVOICE_PAYMENT_AUTHORIZED, INVOICE_PAYMENT_REFUSED, INVOICE_REFUNDED, INVOICE_CHARGEBACK, ...), onboarding events (ONBOARDING_STATUS_UPDATED, ONBOARDING_PROCESSING_FAILED, ...), and payout report events. The same list is shown on the dashboard's webhook settings page when choosing which events to subscribe to.
Example webhook payload:
{
  "data": {
    "unique_id": "i0n00sdQKSgyshUpV5CWYtID2k1judsrgGBl1lYxssycEBN1d1",
    "account_id": 41,
    "invoice_id": "RE-21243",
    "amount": 10000,
    "customer_id": "9131542",
    "customer_reference": "PO-88231",
    "currency": "NOK",
    "payment_url": "https://pay.amili.no/pay-invoice/i0n00sdQKSgyshUpV5CWYtID2k1judsrgGBl1lYxssycEBN1d1"
  },
  "event": "INVOICE_PAYMENT_AUTHORIZED",
  "message": "Invoice payment is authorized."
}
Every request is signed - verify the X-AmiliPay-Signature header, computed as hash_hmac('sha256', payload, secret), where payload is the raw JSON request body (the timestamp is not part of the signed string). The X-AmiliPay-Timestamp header carries the delivery time separately; as a general precaution, reject deliveries whose timestamp is more than 5 minutes old.

4. Recurring payments#

Recurring payments must be enabled by customer service for the merchant. To enable it, set the is_recurring flag when creating the invoice. From then on, reference the original invoice via recurring_invoice_id when creating new invoices for the same customer.
The first time you pass is_recurring: true without recurring_invoice_id, you'll receive an INVOICE_RECURRING_INITIATED webhook - redirect the customer to the payment window to store their payment details.
After a successful payment you'll receive INVOICE_PAYMENT_AUTHORIZED with is_recurring: true and a unique_id - store that unique_id as the reference for this customer's stored payment details.
If a recurring charge fails, you'll receive INVOICE_PAYMENT_REFUSED - ask the customer to pay the invoice manually via the payment window.
If automatic payment fails 10 times with the same token, the token is deleted and you'll receive INVOICE_RECURRING_TOKEN_DELETED.

Payouts#

Payouts to a merchant's bank account are swept automatically - daily by default, configurable to weekly or monthly per merchant. List and track them with GET /payouts and GET /payouts/{payout_id} (with GET /payouts/{payout_id}/details for the underlying transactions). Status is one of Pending, Processing, Completed, Failed, or Returned (a bank-side failure that reverses a previously completed payout).

Testing payments#

Payments are processed through Adyen under the hood, so sandbox testing uses Adyen's test environment and test cards. To test different authorisation outcomes, change the name on the card to one of the values below.
TypeCard numberExpiry DateSecurity Code (CVC/CVV/CID)
3D Secure4917 6100 0000 000003/30737
Visa4111 1111 1111 111103/30737

Response codes#

#holderNamerefusalReasonresultCode
0UNKNOWNUnknownError
1APPROVED-Authorised
2DECLINEDRefusedRefused
3REFERRALReferralRefused
4ERRORAcquirer ErrorError
5BLOCK_CARDBlocked CardRefused
6CARD_EXPIREDExpired CardRefused
7INVALID_AMOUNTInvalid AmountRefused
8INVALID_CARD_NUMBERInvalid Card NumberRefused
9ISSUER_UNAVAILABLEIssuer UnavailableRefused
10NOT_SUPPORTEDNot supportedRefused
11NOT_3D_AUTHENTICATED3D Not AuthenticatedRefused
12NOT_ENOUGH_BALANCENot enough balanceRefused
13PENDING-Received
14ACQUIRER_FRAUDAcquirer FraudRefused
15CANCELLEDCancelledRefused
16SHOPPER_CANCELLEDShopper CancelledRefused
17INVALID_PINInvalid PinRefused
18PIN_TRIES_EXCEEDEDPin tries exceededRefused
19PIN_VALIDATION_NOT_POSSIBLEPin validation not possibleRefused
20FRAUDFRAUDRefused
21NOT_SUBMITTEDNot SubmittedRefused
22FRAUD_CANCELLEDFRAUD-CANCELLEDCancelled
23TRANSACTION_NOT_PERMITTEDTransaction Not PermittedRefused
24CVC_DECLINEDCVC DeclinedRefused
25RESTRICTED_CARDRestricted CardRefused
26REVOCATION_OF_AUTHRevocation Of AuthRefused
27DECLINED_NON_GENERICDeclined Non GenericRefused
28WITHDRAWAL_AMOUNT_EXCEEDEDWithdrawal amount exceededRefused
29WITHDRAWAL_COUNT_EXCEEDEDWithdrawal count exceededRefused
30PARTIALLY_APPROVED-Authorised
31ISSUER_SUSPECTED_FRAUDIssuer Suspected FraudRefused
32AVS_DECLINEDAVS DeclinedRefused
33PIN_REQUIREDCard requires online pinRefused
34NO_CHECKING_ACCOUNT_AVAILABLE_ON_CARDNo checking account available on CardRefused
35NO_SAVINGS_ACCOUNT_AVAILABLE_ON_CARDNo savings account available on CardRefused
36MOBILE_PIN_REQUIREDMobile PIN requiredRefused
37CONTACTLESS_FALLBACKContactless fallbackRefused
38AUTHENTICATION_REQUIREDAuthentication requiredRefused
39RREQ_NOT_RECEIVEDRReq not received from DSRefused
Card numbers and outcome codes above are Adyen's own test-environment values - confirm with your integration contact if you hit a mismatch.

Creating customer account#

"Customer" here means the merchant account you're onboarding (account_id) - not the customer_id field on an invoice, which is just your own free-text reference for the invoice's payer. There is no separate customer entity: account_id is the one durable identifier used throughout the rest of the API. customer_id and customer_reference are both your own free-text values on an invoice - use customer_id for the payer's identifier in your system and customer_reference for any additional reference (e.g. a PO number) you want echoed back on the invoice and its webhooks.
There are two ways to complete onboarding once you've called POST /customers (see Integration flow, step 1):
Hosted onboarding: use the onboarding_token from the response with the embedded widget - the customer approves the agreement and fills in their own KYC details.
Self-hosted onboarding: submit agreement approval and KYC data yourself against the onboarding record already created for you, then add onboarding documents for the company and its personas, then submit for review.
Notes:
Register a webhook for onboarding events so you know when a merchant is COMPLETED and ready to accept payments.
To fully onboard a customer you must provide all required fields on both the onboarding and onboarding-documents endpoints.
It's recommended to do a full onboarding via the hosted flow first and inspect the resulting onboarding record to see how the endpoints fit together, or book a call with your integration contact for guidance.

Managing dashboard users#

Partner and admin API keys can also manage the dashboard login accounts ("users") within their account hierarchy via GET/POST /users and GET/PUT/DELETE /users/{user_id}. These are team-member logins for your own staff to access the dashboard - not customers or invoice payers. See the OpenAPI reference for the full request/response contract.

Embedded Widget#

The embedded widget gives a customer access to onboarding without leaving your platform. Create a customer via the API to get an onboarding_token, then load the widget script and pass the token to it:
<zettr-widget token="{onboarding_token}"></zettr-widget>
<script type="text/javascript" src="https://pay.amili.no/widget/widget.js"></script>
(The <zettr-widget> element name is legacy naming from the widget's original build - it's correct as shown above, just not renamed yet.) The token does not expire, but treat it as a secret - anyone holding it can access that onboarding session.
Embedding domain: by default the widget only loads in a frame on its own origin (self). To embed it on your own site, set your account's WIDGET_DOMAIN setting (via PUT /settings/widget-domain) to your site's domain(s) - a comma-separated list, e.g. partner.com,app.partner.com. Requests from an origin not on that list are rejected.
Modified at 2026-09-25 07:16:01
Previous
Check API health
Next
Industry Categories Reference
Built with