ahlan hamad

Setup guide · Odoo payroll journals

Set up Odoo payroll journals: step by step

This guide is for two people working together: your Odoo admin, who creates the API key and knows your chart of accounts, and the person who runs payroll in AhlanHamad, who connects Odoo and maps the accounts. Follow it in order. Every label below is the one you will see on screen.

Updated 12 October 2026

1. Before you start

CheckWhat you need
Odoo versionOdoo 17, 18 or 19. It has been tested end to end on real Odoo 18 and Odoo 19 databases (11 Oct 2026): connecting, loading accounts, mapping, sending journals, automatic posting and reversing a deleted run. Odoo 19 and later use Odoo's newer JSON-2 API; Odoo 17 uses the same older API as Odoo 18 but has not been run against a live Odoo 17 database yet. As with any new connection, check your first journals in Odoo closely and tell us if anything looks wrong.
Odoo planOn odoo.com you need the Custom plan: Odoo's documentation says the external API, which this connection uses, is not available on the One App Free or Standard plans (Odoo docs). Odoo.sh and Odoo on your own server work too, as long as the server has a public https address that can be reached over the internet.
Accounting in OdooThe Accounting app installed (in Odoo Community it is called Invoicing), with your chart of accounts set up, and at least one journal of type Miscellaneous. Odoo creates one called Miscellaneous Operations; many companies add a separate Payroll journal so these entries are easy to find.
An Odoo user for the connectionEntries are created and posted in Odoo as this user. It must be able to create and post journal entries in the company payroll is booked in. Odoo recommends a dedicated user for integrations rather than a person's own account (Odoo docs).
In AhlanHamadA company admin who can manage settings (to connect Odoo and save the mapping), and the person who finalizes and pays payroll. Your accountant should help with the mapping.

Only totals are sent to Odoo: one line per account, never a line per employee. Names, IDs and individual salaries stay in AhlanHamad.

2. In Odoo: create an API key and find your database name

Do this signed in to Odoo as the user the connection will use. Menu names below are from Odoo's documentation for versions 17, 18 and 19 (17, 18, 19).

  1. Open your user menu (your name or picture, top right) and choose Preferences (called My Profile in some versions).
  2. Open the Account Security tab and click New API Key. Odoo asks for your password to confirm.
  3. Under Description, write something you will recognise later, for example AhlanHamad payroll.
  4. On Odoo 18 and 19, also choose a Duration. Pick the longest one Odoo offers you; an Odoo administrator can choose Persistent Key, which does not expire. Odoo 17 does not ask for one.
  5. Click Generate Key and copy the key straight away. Odoo shows it only once; if you lose it, delete it and create a new one.
  6. Note your login: the user's login, usually an email address (Settings → Users shows it).

Keys expire on Odoo 18 and 19. AhlanHamad shows this under the key field and on the connected card: “Odoo API keys can expire (Odoo 18+ asks for a duration). When yours does, journals wait until you reconnect with a new key — pick a long duration or a persistent key if your Odoo admin allows.” Other users than Odoo administrators are limited by Odoo, by default to three months or less (Odoo source). Nothing is lost when a key expires: reconnecting with a new key (section 3) is what sends the held journals. Put a reminder in your calendar a few days before the key runs out.

Your database name

3. In AhlanHamad: connect Odoo

  1. Go to Integrations and open Odoo ERP. Stay on the Connection tab.
  2. Odoo Instance URL: the address you open Odoo at, for example https://mycompany.odoo.com. If you leave out https:// it is added for you, and if you paste the address of an Odoo page (for example …/odoo/action-123) it is cut back to the server. An http:// address, or one that only works inside your office network, is refused with a message saying why (section 7).
  3. Database Name: the name from section 2.
  4. Odoo login (email): the email you sign in to Odoo with — the same user the API key was created for. Odoo 17 and 18 need it.
  5. API key: paste the key from section 2 (not your Odoo password). The note under this field reminds you that Odoo keys can expire.
  6. API: leave it on Detect automatically. Change it only if the connection fails because your server hides its version.
  7. Click Connect to Odoo. If a field is missing or the address is wrong, it says which. Otherwise the button shows Verifying Connection while we read your Odoo version and test the key.

When it works you see Connected successfully with your Odoo company name, and the card shows Connected to Odoo ERP, your Instance URL and Database Name, and the API in use: JSON-2 · Odoo 19.0 on Odoo 19 and later, or JSON-RPC (legacy) · Odoo 18.0 (or 17.0) on older versions. Your key is stored encrypted and never shown again; the card repeats the key-expiry note.

Already sending payroll to another accounting system? If another one is connected and receiving payroll, AhlanHamad asks first: “Connect a second accounting system?” If you connect Odoo too, every payroll run is posted to both and your payroll costs are booked twice. If you are moving to Odoo, click Cancel, disconnect the other system first, then connect Odoo.

4. Pick the company and journal, then map your accounts

  1. Open the Field Mapping tab. The card is called Post payroll journals to Odoo.
  2. Click Load my accounts. This reads your chart of accounts, companies and journals from Odoo.
  3. If your Odoo user can reach more than one company, Choose the company payroll journals go to. The card then shows Posting to that company and its Base currency.
  4. Under Odoo journal, choose the Miscellaneous journal entries are posted in. Only journals of type Miscellaneous are listed. To add a Payroll journal, create it in Odoo first (Accounting → Configuration → Journals → New, type Miscellaneous), then click Reload accounts.
  5. Map each Ahlan Hamad account to an Odoo account (table below). Some are pre-selected and marked Suggested when the match is clear; check every one with your accountant.
  6. Click Save mapping. When nothing is missing the card says Mapping complete. Until then it says “Posting is on hold until every required account is mapped.”
  7. If you pay any payroll in a currency other than your Odoo company's, decide on Post runs in other currencies (section 5).

Which Odoo account for each payroll account

CodeAhlan Hamad accountNeededTypical Odoo account type
5100Salaries — basic, other allowances, overtime & additionsRequiredExpenses
5400Housing allowanceRequiredExpenses
5500Transport allowanceRequiredExpenses
5200Employer social-insurance contributionRequiredExpenses
5300End-of-service expenseRequiredExpenses
2100Net salaries payableRequiredCurrent Liabilities (not Payable)
2200Social insurance payable (employee + employer)RequiredCurrent Liabilities
2300End-of-service provisionRequiredNon-current Liabilities
1101Bank account salaries are paid fromRequiredBank and Cash, or a clearing account (see tip)
2700Deductions withheld (loans, penalties, unpaid leave)Only if usedCurrent Liabilities
5810Bank transfer charges on salariesOnly if usedExpenses
5310DIFC DEWS employer contributionOnly if usedExpenses
2310DIFC DEWS payableOnly if usedCurrent Liabilities
5900Foreign-exchange gain/loss on payroll (only if a run in another currency is paid at a different rate)Only if usedYour exchange-difference account

End-of-service is not on the payroll journal. It is its own journal each month (5300 End-of-service expense / 2300 End-of-service provision).

5. What gets posted, and when

When this happens in AhlanHamadOdoo receivesDated
A payroll run is finalized (Finalize)Payroll accrual: salaries and allowances, employer social insurance and the payables they create (debits 5100–5500, credits 2100, 2200 and, if used, 2700)The last day of the payroll month
The run is paid (Mark as Paid, or CEO Sign-off & Pay)Salary payment: debit 2100 Net salaries payable, credit 1101The day the run was signed off and paid
Bank transfer charges are recorded on a paid runBank charges: debit 5810, credit 1101The pay day
A month endsEnd-of-service accrual: debit 5300, credit 2300 — sent automatically on the 1st of the next month. You can also run it by hand for a finished month with Run Monthly Accrual on the Finance page.The last day of that month
A run is deleted, or a posted journal is correctedA reversal: the same lines with debit and credit swapped, linked in Odoo to the entry it reverses (Odoo shows “Reversal of …”). A corrected run is then posted again as a new entry.The day of the change

6. Check your first payroll in Odoo

  1. In AhlanHamad, open the payroll run. The Odoo journals card lists each journal (Payroll accrual, Salary payment, …) with its status. Posted means Odoo has it, and the card shows Odoo's own entry number, for example Journal MISC/2026/10/0001.
  2. In Odoo, go to Accounting → Accounting → Journal Entries (Odoo menus).
  3. Type the entry number, or AH, in the search box and choose Search Journal Entry for: …. This searches entry numbers and references.
  4. Open the entry and check: the journal you picked, the date (the last day of the payroll month for the accrual), the status Posted, one line per mapped account, and totals that match the payroll run in AhlanHamad.
  5. After the run is paid, check the Salary payment entry the same way, and match it to your bank as described in section 4.

Statuses on the run card: Queued and Sending (on its way), Waiting (another journal must reach Odoo first), Retrying (Odoo or the network was busy; we try again automatically), Posted, On hold (needs you; the reason is shown), Failed (Odoo refused it; the reason is shown), Not needed (nothing to send).

7. Troubleshooting

Company admins who can manage settings, and finance managers, also get an in-app notice and an email when Odoo journals are held or fail: one per problem, a reminder after three days, and a short note when it clears. No amounts, names or Odoo errors are put in the email; open the payroll run to see the reason.

When connecting (Connection tab)

If connecting fails, the Connection tab says why in a plain sentence (below). Under it, Details for support holds the technical text; send that to us if you need help. The same sentence appears on the payroll run when a journal is held for a connection problem.

What you seeWhat to do
That isn't a web address. Enter the address you open Odoo at, for example https://mycompany.odoo.com.Type the address you open Odoo at, as in your browser's address bar.
The Odoo address must start with https://. Ahlan Hamad only connects to Odoo over a secure connection, so your API key is never sent in the clear.Use the https:// address. If your Odoo only has an http:// address, your Odoo partner needs to add an https certificate first.
Ahlan Hamad can only reach Odoo servers that are on the public internet. If your Odoo runs inside your office network, ask your Odoo partner to publish it over https.Odoo on an office network or VPN has to be published on the internet over https first.
We couldn't find this address on the public internet. Check it is spelled exactly as in your browser's address bar. If your Odoo only opens inside your office network, ask your Odoo partner to publish it over https.Copy the address from your browser while signed in to Odoo. Check it opens from outside your office network.
Your Odoo server didn't answer in time. Check the address opens in your browser and try again. If it is behind a firewall, ask your Odoo partner to allow connections from the internet.Check Odoo opens in a browser from outside your office network, then try again.
Your Odoo server's security certificate isn't valid, so we stopped before sending your key. Ask your Odoo partner to install a valid https certificate, then try again.Your Odoo partner installs a valid certificate; then connect again.
We couldn't reach your Odoo server. Check the address opens in your browser and try again.Check the address and that Odoo is up, then try again.
Odoo has no database with that name. Copy the exact database name — on odoo.com it is often the first part of your address (mycompany for mycompany.odoo.com); otherwise your Odoo partner can tell you.See “Your database name” in section 2.
Odoo refused the login and API key. Check the login is the email you sign in to Odoo with and that the API key was created by that same user.Check the login and that the key belongs to that user. If in doubt, create a new key (section 2). On odoo.com the message adds a line about the Custom plan.
Odoo no longer accepts this API key. Odoo API keys can expire (Odoo 18+ asks for a duration), so yours may have expired — create a new key in Odoo and reconnect. Journals wait until you do.Create a new key in Odoo (section 2) and connect again. Held journals are then sent by themselves.
Odoo refused the key because no login was sent with it. Enter your Odoo login (the email you sign in with) as well as the API key — Odoo 17 and 18 need both.Fill in Odoo login (email).
Enter your Odoo login as the email you sign in with (it can't contain a colon).Enter the email address only.
Your Odoo plan doesn't allow external API access (on odoo.com this needs the Custom plan).On odoo.com, move to the Custom plan, or use Odoo.sh or your own server.
Your Odoo server didn't answer the API we tried. Reconnect with API set to Detect automatically, or choose the other API.Set API to Detect automatically and connect again.
The connection to Odoo failed. If it keeps happening, send the details below to support.Open Details for support and send us what it says.
Your Odoo server did not report its version, so we used JSON-RPC.Shown after connecting. If you run Odoo 19 or later, connect again and choose JSON-2 under API.

On the payroll run: On hold

A held journal is waiting, not lost. Fix the reason and it goes, either by itself or when you press Retry on the run card.

What you seeWhat to do
Map these accounts first: 5400, 5500.Map the listed account codes on the Field Mapping tab and click Save mapping, then Retry.
Load your accounts and save the mapping on the integration page first.On the Field Mapping tab, click Load my accounts, choose the Odoo journal, save the mapping, then Retry.
… mapped to an account that can't be used in a journal (Accounts Payable or Receivable, a system or bank account, or an account with no code). Pick another account on the integration page.In Odoo terms: a Receivable or Payable account. Map those codes to a Current Liabilities account (or another suitable account), save, then Retry.
This run's currency differs from your books. Allow other-currency posting to send it.Switch on Post runs in other currencies on the Field Mapping tab, then Retry. Or keep that run out of Odoo.
The connection needs to be renewed. Reconnect and try again. — with, for Odoo: “Odoo API keys can expire (Odoo 18+ asks for a duration), so the key may have expired — reconnect Odoo with a new key.”Odoo refused the key (it expired, was deleted, or the user lost access), or the Odoo address or database changed. Create a new key in Odoo and connect again (section 3). Journals held for this reason are sent automatically once you reconnect. If you connected a different database, click Reload accounts and check the mapping first.
Not connected, or posting is switched off.Connect Odoo again on the Connection tab. Held journals are sent automatically once you reconnect.

On the payroll run: Failed

These come back from Odoo, in English, as Odoo wrote them. Fix the cause in Odoo or in the mapping, then press Retry. A retry never creates a second entry.

What you seeWhat to do
Odoo rejected the journal (400). followed by Odoo's own messageRead Odoo's message. A common one: the date falls before your Odoo lock date, so the period is closed. Ask your accountant to change the lock date, or reverse and correct the run in AhlanHamad.
Odoo refused access (403). The connection may lack permission to post journals, or the organisation was disconnected — reconnect Odoo.The Odoo user can't create or post entries in that company. Give it accounting rights and access to the company, then connect again.
Odoo could not find the company or an account this journal points at (404). Check the account mapping belongs to the connected company.A mapped account or the journal was deleted or archived in Odoo. Click Reload accounts, fix the mapping and journal, save, then Retry.
Created as a draft but not posted: …The entry is in Odoo as a draft and Odoo refused to post it; the reason follows. Fix it, then Retry: the same draft is posted, never a second one.
An Odoo journal or account id in the mapping is not a number. Reload your Odoo accounts and save the mapping again.Click Reload accounts, save the mapping again, then Retry.
This run's payroll accrual journal did not reach Odoo. Retry the accrual first, then retry this payment, so it clears exactly the salaries payable the accrual booked.Retry the Payroll accrual line first, then the Salary payment line.
No exchange rate from … to … is available.Try again later, or contact us.
… — gave up after 6 attempts.Odoo or the network kept failing. Check Odoo is up, then press Retry.

Two accounting systems

If the Odoo page or the payroll run says “Payroll is being posted to …” with more than one system, every run is booked in each of them. If you keep your books only in Odoo, disconnect the others so payroll costs aren't counted twice.

8. Disconnecting

  1. In AhlanHamad, go to Integrations → Odoo ERP → Connection and click Disconnect Odoo. The stored key is deleted.
  2. In Odoo, delete the API key too: Preferences → Account Security, then remove the AhlanHamad key.

Odoo sources used in this guide

About AhlanHamad × Odoo· All integrations